• 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 #include "display_manager_lite.h"
21 #include "key_map_manager.h"
22 #include "key_command_handler_util.h"
23 #include "key_unicode_transformation.h"
24 #include "misc_product_type_parser.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 constexpr int32_t SWAP_VOLUME_KEYS_ON_FOLD { 0 };
36 class FoldStatusCallback : public Rosen::DisplayManagerLite::IFoldStatusListener {
37 public:
38     FoldStatusCallback() = default;
39     ~FoldStatusCallback() = default;
OnFoldStatusChanged(Rosen::FoldStatus foldStatus)40     void OnFoldStatusChanged(Rosen::FoldStatus foldStatus) override
41     {
42         std::lock_guard<std::mutex> guard(mutex_);
43         foldStatus_ = foldStatus;
44     }
GetFoldStatus()45     Rosen::FoldStatus GetFoldStatus()
46     {
47         std::lock_guard<std::mutex> guard(mutex_);
48         return foldStatus_;
49     }
50 private:
51     std::mutex mutex_;
52     Rosen::FoldStatus foldStatus_ { Rosen::FoldStatus::UNKNOWN };
53 };
54 sptr<FoldStatusCallback> g_foldStatusCallback { nullptr };
55 } // namespace
56 
KeyEventNormalize()57 KeyEventNormalize::KeyEventNormalize() {}
58 
~KeyEventNormalize()59 KeyEventNormalize::~KeyEventNormalize() {}
60 
Init()61 void KeyEventNormalize::Init()
62 {
63     g_foldStatusCallback = new (std::nothrow) FoldStatusCallback();
64     CHKPV(g_foldStatusCallback);
65     Rosen::DisplayManagerLite::GetInstance().RegisterFoldStatusListener(g_foldStatusCallback);
66 }
67 
GetKeyEvent()68 std::shared_ptr<KeyEvent> KeyEventNormalize::GetKeyEvent()
69 {
70     if (keyEvent_ == nullptr) {
71         keyEvent_ = KeyEvent::Create();
72     }
73     return keyEvent_;
74 }
75 
Normalize(struct libinput_event * event,std::shared_ptr<KeyEvent> keyEvent)76 int32_t KeyEventNormalize::Normalize(struct libinput_event *event, std::shared_ptr<KeyEvent> keyEvent)
77 {
78     CALL_DEBUG_ENTER;
79     CHKPR(event, PARAM_INPUT_INVALID);
80     CHKPR(keyEvent, ERROR_NULL_POINTER);
81     keyEvent->UpdateId();
82     StartLogTraceId(keyEvent->GetId(), keyEvent->GetEventType(), keyEvent->GetKeyAction());
83     auto data = libinput_event_get_keyboard_event(event);
84     CHKPR(data, ERROR_NULL_POINTER);
85 
86     auto device = libinput_event_get_device(event);
87     CHKPR(device, ERROR_NULL_POINTER);
88     int32_t deviceId = INPUT_DEV_MGR->FindInputDeviceId(device);
89     int32_t keyCode = static_cast<int32_t>(libinput_event_keyboard_get_key(data));
90     MMI_HILOGD("The linux input:%{private}d", keyCode);
91     keyCode = KeyMapMgr->TransferDeviceKeyValue(device, keyCode);
92     if (keyCode == KeyEvent::KEYCODE_UNKNOWN) {
93         MMI_HILOGE("The key value is unknown");
94         return RET_ERR;
95     }
96     int32_t keyAction = (libinput_event_keyboard_get_key_state(data) == 0) ?
97         (KeyEvent::KEY_ACTION_UP) : (KeyEvent::KEY_ACTION_DOWN);
98     keyCode = TransformVolumeKey(device, keyCode, keyAction);
99     auto preAction = keyEvent->GetAction();
100     if (preAction == KeyEvent::KEY_ACTION_UP) {
101         std::optional<KeyEvent::KeyItem> preUpKeyItem = keyEvent->GetKeyItem();
102         if (preUpKeyItem) {
103             keyEvent->RemoveReleasedKeyItems(*preUpKeyItem);
104         } else {
105             MMI_HILOGE("The preUpKeyItem is nullopt");
106         }
107     }
108     uint64_t time = libinput_event_keyboard_get_time_usec(data);
109     keyEvent->SetActionTime(time);
110     keyEvent->SetAction(keyAction);
111     keyEvent->SetDeviceId(deviceId);
112     keyEvent->SetSourceType(InputEvent::SOURCE_TYPE_UNKNOWN);
113     keyEvent->SetKeyCode(keyCode);
114     keyEvent->SetKeyAction(keyAction);
115     StartLogTraceId(keyEvent->GetId(), keyEvent->GetEventType(), keyEvent->GetKeyAction());
116     if (keyEvent->GetPressedKeys().empty()) {
117         keyEvent->SetActionStartTime(time);
118     }
119 
120     KeyEvent::KeyItem item;
121     bool isKeyPressed = (libinput_event_keyboard_get_key_state(data) != KEYSTATUS);
122     item.SetDownTime(time);
123     item.SetKeyCode(keyCode);
124     item.SetDeviceId(deviceId);
125     item.SetPressed(isKeyPressed);
126     item.SetUnicode(KeyCodeToUnicode(keyCode, keyEvent));
127 
128     HandleKeyAction(device, item, keyEvent);
129 
130     int32_t keyIntention = KeyItemsTransKeyIntention(keyEvent->GetKeyItems());
131     keyEvent->SetKeyIntention(keyIntention);
132     return RET_OK;
133 }
134 
HandleKeyAction(struct libinput_device * device,KeyEvent::KeyItem & item,std::shared_ptr<KeyEvent> keyEvent)135 void KeyEventNormalize::HandleKeyAction(struct libinput_device* device, KeyEvent::KeyItem &item,
136     std::shared_ptr<KeyEvent> keyEvent)
137 {
138     CHKPV(device);
139     CHKPV(keyEvent);
140     int32_t keyAction = keyEvent->GetAction();
141     int32_t keyCode = keyEvent->GetKeyCode();
142     if (keyAction == KeyEvent::KEY_ACTION_DOWN) {
143         keyEvent->AddPressedKeyItems(item);
144     }
145     if (keyAction == KeyEvent::KEY_ACTION_UP) {
146         int32_t funcKey = keyEvent->TransitionFunctionKey(keyCode);
147         if (funcKey != KeyEvent::UNKNOWN_FUNCTION_KEY) {
148             int32_t funKeyState = libinput_get_funckey_state(device, funcKey);
149             int32_t ret = keyEvent->SetFunctionKey(funcKey, funKeyState);
150             if (ret == funcKey) {
151                 MMI_HILOGI("Set function key:%{public}d to state:%{public}d succeed",
152                            funcKey, funKeyState);
153             }
154         }
155         std::optional<KeyEvent::KeyItem> pressedKeyItem = keyEvent->GetKeyItem(keyCode);
156         if (pressedKeyItem) {
157             item.SetDownTime(pressedKeyItem->GetDownTime());
158         } else {
159             MMI_HILOGE("Find pressed key failed:%{private}d", keyCode);
160         }
161         keyEvent->RemoveReleasedKeyItems(item);
162         keyEvent->AddPressedKeyItems(item);
163     }
164 }
165 
ResetKeyEvent(struct libinput_device * device)166 void KeyEventNormalize::ResetKeyEvent(struct libinput_device* device)
167 {
168     if (INPUT_DEV_MGR->IsKeyboardDevice(device) || INPUT_DEV_MGR->IsPointerDevice(device)) {
169         bool newKeyEventJustCreated = false;
170         if (keyEvent_ == nullptr) {
171             keyEvent_ = KeyEvent::Create();
172             newKeyEventJustCreated = true;
173         }
174         CHKPV(keyEvent_);
175 
176         if (!libinput_has_event_led_type(device)) {
177             // skip if this device does not have led lights.
178             return;
179         }
180 
181         const std::vector<int32_t> funcKeys = {
182             KeyEvent::NUM_LOCK_FUNCTION_KEY,
183             KeyEvent::CAPS_LOCK_FUNCTION_KEY,
184             KeyEvent::SCROLL_LOCK_FUNCTION_KEY
185         };
186 #ifdef OHOS_BUILD_ENABLE_VKEYBOARD
187         if (newKeyEventJustCreated) {
188             // if key event just created, set keyevent from this new device.
189             MMI_HILOGI("Reset key event function key state based on the new added device's led");
190             for (const auto &funcKey : funcKeys) {
191                 keyEvent_->SetFunctionKey(funcKey, libinput_get_funckey_state(device, funcKey));
192             }
193         } else {
194             // otherwise, set this new device's function key state based on the key event.
195             for (const auto &funcKey : funcKeys) {
196                 LibinputAdapter::DeviceLedUpdate(device, funcKey, keyEvent_->GetFunctionKey(funcKey));
197             }
198         }
199 #else // OHOS_BUILD_ENABLE_VKEYBOARD
200         for (const auto &funcKey : funcKeys) {
201             keyEvent_->SetFunctionKey(funcKey, libinput_get_funckey_state(device, funcKey));
202         }
203 #endif // OHOS_BUILD_ENABLE_VKEYBOARD
204     }
205 }
206 
SetShieldStatus(int32_t shieldMode,bool isShield)207 int32_t KeyEventNormalize::SetShieldStatus(int32_t shieldMode, bool isShield)
208 {
209     std::lock_guard<std::mutex> guard(mtx_);
210     MMI_HILOGI("Last shield mode:%{public}d, set shield mode:%{public}d, status:%{public}d",
211         lastShieldMode_, shieldMode, isShield);
212     auto iter = shieldStatus_.find(lastShieldMode_);
213     if (isShield) {
214         if (lastShieldMode_ == shieldMode) {
215             MMI_HILOGI("Last shield mode equal with shield mode");
216         } else if (iter != shieldStatus_.end()) {
217             iter->second = false;
218         } else {
219             MMI_HILOGI("Last shield mode unset");
220         }
221         lastShieldMode_ = shieldMode;
222     } else if (lastShieldMode_ != shieldMode) {
223         MMI_HILOGI("Shield mode:%{public}d is already false", shieldMode);
224     } else {
225         MMI_HILOGI("The lastShieldMode_ unset");
226         lastShieldMode_ = SHIELD_MODE::UNSET_MODE;
227     }
228     iter = shieldStatus_.find(shieldMode);
229     if (iter == shieldStatus_.end()) {
230         MMI_HILOGE("Find shieldMode:%{public}d failed", shieldMode);
231         return RET_ERR;
232     }
233     iter->second = isShield;
234     MMI_HILOGI("Last shield mode:%{public}d, set shield mode:%{public}d, status:%{public}d",
235         lastShieldMode_, shieldMode, isShield);
236     return RET_OK;
237 }
238 
GetShieldStatus(int32_t shieldMode,bool & isShield)239 int32_t KeyEventNormalize::GetShieldStatus(int32_t shieldMode, bool &isShield)
240 {
241     CALL_DEBUG_ENTER;
242     std::lock_guard<std::mutex> guard(mtx_);
243     auto iter = shieldStatus_.find(shieldMode);
244     if (iter == shieldStatus_.end()) {
245         MMI_HILOGE("Find shieldMode:%{public}d failed", shieldMode);
246         return RET_ERR;
247     }
248     isShield = iter->second;
249     MMI_HILOGI("Last shield mode:%{public}d, get shield mode:%{public}d, status:%{public}d",
250         lastShieldMode_, shieldMode, isShield);
251     return RET_OK;
252 }
253 
GetCurrentShieldMode()254 int32_t KeyEventNormalize::GetCurrentShieldMode()
255 {
256     std::lock_guard<std::mutex> guard(mtx_);
257     return lastShieldMode_;
258 }
259 
SetCurrentShieldMode(int32_t shieldMode)260 void KeyEventNormalize::SetCurrentShieldMode(int32_t shieldMode)
261 {
262     std::lock_guard<std::mutex> guard(mtx_);
263     lastShieldMode_ = shieldMode;
264 }
265 
ReadProductConfig(InputProductConfig & config) const266 void KeyEventNormalize::ReadProductConfig(InputProductConfig &config) const
267 {
268     config = InputProductConfig {};
269     char cfgName[] { "etc/input/input_product_config.json" };
270     char buf[MAX_PATH_LEN] {};
271     char *cfgPath = ::GetOneCfgFile(cfgName, buf, sizeof(buf));
272     if (cfgPath == nullptr) {
273         MMI_HILOGE("No '%{private}s' was found", cfgName);
274         return;
275     }
276     MMI_HILOGI("Input product config:%{private}s", cfgPath);
277     ReadProductConfig(std::string(cfgPath), config);
278 }
279 
ReadProductConfig(const std::string & cfgPath,InputProductConfig & config) const280 void KeyEventNormalize::ReadProductConfig(const std::string &cfgPath, InputProductConfig &config) const
281 {
282     std::string cfg = ReadJsonFile(cfgPath);
283     JsonParser parser(cfg.c_str());
284     if (!cJSON_IsObject(parser.Get())) {
285         MMI_HILOGE("Not json format");
286         return;
287     }
288     cJSON *jsonKeyboard = cJSON_GetObjectItemCaseSensitive(parser.Get(), "keyboard");
289     if (!cJSON_IsObject(jsonKeyboard)) {
290         MMI_HILOGE("The jsonKeyboard is not object");
291         return;
292     }
293     cJSON *jsonVolumeSwap = cJSON_GetObjectItemCaseSensitive(jsonKeyboard, "volumeSwap");
294     if (!cJSON_IsObject(jsonVolumeSwap)) {
295         MMI_HILOGE("The jsonVolumeSwap is not object");
296         return;
297     }
298     cJSON *jsonWhen = cJSON_GetObjectItemCaseSensitive(jsonVolumeSwap, "when");
299     if (!cJSON_IsNumber(jsonWhen)) {
300         MMI_HILOGE("The jsonWhen is not number");
301         return;
302     }
303     if (static_cast<int32_t>(cJSON_GetNumberValue(jsonWhen)) == SWAP_VOLUME_KEYS_ON_FOLD) {
304         config.volumeSwap_ = VolumeSwapConfig::SWAP_ON_FOLD;
305     } else {
306         config.volumeSwap_ = VolumeSwapConfig::NO_VOLUME_SWAP;
307     }
308     MMI_HILOGI("keyboard.volumeSwap:%{public}d", static_cast<int32_t>(config.volumeSwap_));
309 }
310 
CheckProductParam(InputProductConfig & productConfig) const311 void KeyEventNormalize::CheckProductParam(InputProductConfig &productConfig) const
312 {
313     if (productConfig.volumeSwap_ != VolumeSwapConfig::NO_CONFIG) {
314         return;
315     }
316     std::vector<std::string> flipVolumeProduct;
317     if (MISC_PRODUCT_TYPE_PARSER.GetFlipVolumeSupportedProduct(flipVolumeProduct) != RET_OK) {
318         MMI_HILOGE("GetFlipVolumeSupportedProduct failed");
319     }
320     std::string product = OHOS::system::GetParameter("const.build.product", "");
321     auto iter = std::find(flipVolumeProduct.begin(), flipVolumeProduct.end(), product);
322     if (iter != flipVolumeProduct.end()) {
323         productConfig.volumeSwap_ = VolumeSwapConfig::SWAP_ON_FOLD;
324     } else {
325         productConfig.volumeSwap_ = VolumeSwapConfig::NO_VOLUME_SWAP;
326     }
327 }
328 
TransformVolumeKey(struct libinput_device * dev,int32_t keyCode,int32_t keyAction) const329 int32_t KeyEventNormalize::TransformVolumeKey(struct libinput_device *dev, int32_t keyCode, int32_t keyAction) const
330 {
331     CHKPR(g_foldStatusCallback, keyCode);
332     static std::once_flag flag;
333     static std::map<int32_t, Rosen::FoldStatus> displayModes {
334         { KeyEvent::KEYCODE_VOLUME_DOWN, Rosen::FoldStatus::UNKNOWN },
335         { KeyEvent::KEYCODE_VOLUME_UP, Rosen::FoldStatus::UNKNOWN },
336     };
337     static InputProductConfig productConfig {};
338 
339     std::call_once(flag, [this]() {
340         ReadProductConfig(productConfig);
341         CheckProductParam(productConfig);
342     });
343     if (productConfig.volumeSwap_ != VolumeSwapConfig::SWAP_ON_FOLD) {
344         return keyCode;
345     }
346     auto iter = displayModes.find(keyCode);
347     if (iter == displayModes.end()) {
348         return keyCode;
349     }
350     if (keyAction == KeyEvent::KEY_ACTION_DOWN) {
351         iter->second = g_foldStatusCallback->GetFoldStatus();
352     }
353     if (iter->second != Rosen::FoldStatus::FOLDED) {
354         return keyCode;
355     }
356     const char *name = libinput_device_get_name(dev);
357     int32_t busType = static_cast<int32_t>(libinput_device_get_id_bustype(dev));
358     MMI_HILOGD("Flip volume keys upon fold: Dev:%{public}s, Bus:%{public}d",
359         name != nullptr ? name : "(null)", busType);
360     if (busType != BUS_HOST) {
361         return keyCode;
362     }
363     return (keyCode == KeyEvent::KEYCODE_VOLUME_DOWN ? KeyEvent::KEYCODE_VOLUME_UP : KeyEvent::KEYCODE_VOLUME_DOWN);
364 }
365 
IsScreenFold()366 bool KeyEventNormalize::IsScreenFold()
367 {
368     CHKPF(g_foldStatusCallback);
369     return g_foldStatusCallback->GetFoldStatus() == Rosen::FoldStatus::FOLDED;
370 }
371 } // namespace MMI
372 } // namespace OHOS
373