• 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 "display_manager.h"
22 #include "key_map_manager.h"
23 #include "key_command_handler_util.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 constexpr int32_t SWAP_VOLUME_KEYS_ON_FOLD { 0 };
36 class FoldStatusCallback : public Rosen::DisplayManager::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::DisplayManager::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 keyCode:%{private}d", keyCode);
91     keyCode = KeyMapMgr->TransferDeviceKeyValue(device, keyCode);
92     int32_t keyAction = (libinput_event_keyboard_get_key_state(data) == 0) ?
93         (KeyEvent::KEY_ACTION_UP) : (KeyEvent::KEY_ACTION_DOWN);
94     keyCode = TransformVolumeKey(device, keyCode, keyAction);
95     auto preAction = keyEvent->GetAction();
96     if (preAction == KeyEvent::KEY_ACTION_UP) {
97         std::optional<KeyEvent::KeyItem> preUpKeyItem = keyEvent->GetKeyItem();
98         if (preUpKeyItem) {
99             keyEvent->RemoveReleasedKeyItems(*preUpKeyItem);
100         } else {
101             MMI_HILOGE("The preUpKeyItem is nullopt");
102         }
103     }
104     uint64_t time = libinput_event_keyboard_get_time_usec(data);
105     keyEvent->SetActionTime(time);
106     keyEvent->SetAction(keyAction);
107     keyEvent->SetDeviceId(deviceId);
108     keyEvent->SetSourceType(InputEvent::SOURCE_TYPE_UNKNOWN);
109     keyEvent->SetKeyCode(keyCode);
110     keyEvent->SetKeyAction(keyAction);
111     StartLogTraceId(keyEvent->GetId(), keyEvent->GetEventType(), keyEvent->GetKeyAction());
112     if (keyEvent->GetPressedKeys().empty()) {
113         keyEvent->SetActionStartTime(time);
114     }
115 
116     KeyEvent::KeyItem item;
117     bool isKeyPressed = (libinput_event_keyboard_get_key_state(data) != KEYSTATUS);
118     item.SetDownTime(time);
119     item.SetKeyCode(keyCode);
120     item.SetDeviceId(deviceId);
121     item.SetPressed(isKeyPressed);
122     item.SetUnicode(KeyCodeToUnicode(keyCode, keyEvent));
123 
124     HandleKeyAction(device, item, keyEvent);
125 
126     int32_t keyIntention = KeyItemsTransKeyIntention(keyEvent->GetKeyItems());
127     keyEvent->SetKeyIntention(keyIntention);
128     return RET_OK;
129 }
130 
HandleKeyAction(struct libinput_device * device,KeyEvent::KeyItem & item,std::shared_ptr<KeyEvent> keyEvent)131 void KeyEventNormalize::HandleKeyAction(struct libinput_device* device, KeyEvent::KeyItem &item,
132     std::shared_ptr<KeyEvent> keyEvent)
133 {
134     CHKPV(device);
135     CHKPV(keyEvent);
136     int32_t keyAction = keyEvent->GetAction();
137     int32_t keyCode = keyEvent->GetKeyCode();
138     if (keyAction == KeyEvent::KEY_ACTION_DOWN) {
139         keyEvent->AddPressedKeyItems(item);
140     }
141     if (keyAction == KeyEvent::KEY_ACTION_UP) {
142         int32_t funcKey = keyEvent->TransitionFunctionKey(keyCode);
143         if (funcKey != KeyEvent::UNKNOWN_FUNCTION_KEY) {
144             int32_t ret = keyEvent->SetFunctionKey(funcKey, libinput_get_funckey_state(device, funcKey));
145             if (ret == funcKey) {
146                 MMI_HILOGD("Set function key:%{public}d to state:%{public}d succeed",
147                            funcKey, keyEvent->GetFunctionKey(funcKey));
148             }
149         }
150         std::optional<KeyEvent::KeyItem> pressedKeyItem = keyEvent->GetKeyItem(keyCode);
151         if (pressedKeyItem) {
152             item.SetDownTime(pressedKeyItem->GetDownTime());
153         } else {
154             MMI_HILOGE("Find pressed key failed, keyCode:%{private}d", keyCode);
155         }
156         keyEvent->RemoveReleasedKeyItems(item);
157         keyEvent->AddPressedKeyItems(item);
158     }
159 }
160 
ResetKeyEvent(struct libinput_device * device)161 void KeyEventNormalize::ResetKeyEvent(struct libinput_device* device)
162 {
163     if (INPUT_DEV_MGR->IsKeyboardDevice(device) || INPUT_DEV_MGR->IsPointerDevice(device)) {
164         if (keyEvent_ == nullptr) {
165             keyEvent_ = KeyEvent::Create();
166         }
167         if (libinput_has_event_led_type(device)) {
168             CHKPV(keyEvent_);
169             const std::vector<int32_t> funcKeys = {
170                 KeyEvent::NUM_LOCK_FUNCTION_KEY,
171                 KeyEvent::CAPS_LOCK_FUNCTION_KEY,
172                 KeyEvent::SCROLL_LOCK_FUNCTION_KEY
173             };
174             for (const auto &funcKey : funcKeys) {
175                 keyEvent_->SetFunctionKey(funcKey, libinput_get_funckey_state(device, funcKey));
176             }
177         }
178     }
179 }
180 
SetShieldStatus(int32_t shieldMode,bool isShield)181 int32_t KeyEventNormalize::SetShieldStatus(int32_t shieldMode, bool isShield)
182 {
183     std::lock_guard<std::mutex> guard(mtx_);
184     MMI_HILOGI("Last shield mode:%{public}d, set shield mode:%{public}d, status:%{public}d",
185         lastShieldMode_, shieldMode, isShield);
186     auto iter = shieldStatus_.find(lastShieldMode_);
187     if (isShield) {
188         if (lastShieldMode_ == shieldMode) {
189             MMI_HILOGI("Last shield mode equal with shield mode");
190         } else if (iter != shieldStatus_.end()) {
191             iter->second = false;
192         } else {
193             MMI_HILOGI("Last shield mode unset");
194         }
195         lastShieldMode_ = shieldMode;
196     } else if (lastShieldMode_ != shieldMode) {
197         MMI_HILOGI("Shield mode:%{public}d is already false", shieldMode);
198     } else {
199         MMI_HILOGI("The lastShieldMode_ unset");
200         lastShieldMode_ = SHIELD_MODE::UNSET_MODE;
201     }
202     iter = shieldStatus_.find(shieldMode);
203     if (iter == shieldStatus_.end()) {
204         MMI_HILOGE("Find shieldMode:%{public}d failed", shieldMode);
205         return RET_ERR;
206     }
207     iter->second = isShield;
208     MMI_HILOGI("Last shield mode:%{public}d, set shield mode:%{public}d, status:%{public}d",
209         lastShieldMode_, shieldMode, isShield);
210     return RET_OK;
211 }
212 
GetShieldStatus(int32_t shieldMode,bool & isShield)213 int32_t KeyEventNormalize::GetShieldStatus(int32_t shieldMode, bool &isShield)
214 {
215     CALL_DEBUG_ENTER;
216     std::lock_guard<std::mutex> guard(mtx_);
217     auto iter = shieldStatus_.find(shieldMode);
218     if (iter == shieldStatus_.end()) {
219         MMI_HILOGE("Find shieldMode:%{public}d failed", shieldMode);
220         return RET_ERR;
221     }
222     isShield = iter->second;
223     MMI_HILOGI("Last shield mode:%{public}d, get shield mode:%{public}d, status:%{public}d",
224         lastShieldMode_, shieldMode, isShield);
225     return RET_OK;
226 }
227 
GetCurrentShieldMode()228 int32_t KeyEventNormalize::GetCurrentShieldMode()
229 {
230     std::lock_guard<std::mutex> guard(mtx_);
231     return lastShieldMode_;
232 }
233 
SetCurrentShieldMode(int32_t shieldMode)234 void KeyEventNormalize::SetCurrentShieldMode(int32_t shieldMode)
235 {
236     std::lock_guard<std::mutex> guard(mtx_);
237     lastShieldMode_ = shieldMode;
238 }
239 
ReadProductConfig(InputProductConfig & config) const240 void KeyEventNormalize::ReadProductConfig(InputProductConfig &config) const
241 {
242     config = InputProductConfig {};
243     char cfgName[] { "etc/input/input_product_config.json" };
244     char buf[MAX_PATH_LEN] {};
245     char *cfgPath = ::GetOneCfgFile(cfgName, buf, sizeof(buf));
246     if (cfgPath == nullptr) {
247         MMI_HILOGE("No '%{public}s' was found", cfgName);
248         return;
249     }
250     MMI_HILOGI("Input product config:%{public}s", cfgPath);
251     ReadProductConfig(std::string(cfgPath), config);
252 }
253 
ReadProductConfig(const std::string & cfgPath,InputProductConfig & config) const254 void KeyEventNormalize::ReadProductConfig(const std::string &cfgPath, InputProductConfig &config) const
255 {
256     std::string cfg = ReadJsonFile(cfgPath);
257     JsonParser parser;
258     parser.json_ = cJSON_Parse(cfg.c_str());
259     if (!cJSON_IsObject(parser.json_)) {
260         MMI_HILOGE("Not json format");
261         return;
262     }
263     cJSON *jsonKeyboard = cJSON_GetObjectItemCaseSensitive(parser.json_, "keyboard");
264     if (!cJSON_IsObject(jsonKeyboard)) {
265         MMI_HILOGE("The jsonKeyboard is not object");
266         return;
267     }
268     cJSON *jsonVolumeSwap = cJSON_GetObjectItemCaseSensitive(jsonKeyboard, "volumeSwap");
269     if (!cJSON_IsObject(jsonVolumeSwap)) {
270         MMI_HILOGE("The jsonVolumeSwap is not object");
271         return;
272     }
273     cJSON *jsonWhen = cJSON_GetObjectItemCaseSensitive(jsonVolumeSwap, "when");
274     if (!cJSON_IsNumber(jsonWhen)) {
275         MMI_HILOGE("The jsonWhen is not number");
276         return;
277     }
278     if (static_cast<int32_t>(cJSON_GetNumberValue(jsonWhen)) == SWAP_VOLUME_KEYS_ON_FOLD) {
279         config.volumeSwap_ = VolumeSwapConfig::SWAP_ON_FOLD;
280     } else {
281         config.volumeSwap_ = VolumeSwapConfig::NO_VOLUME_SWAP;
282     }
283     MMI_HILOGI("keyboard.volumeSwap:%{public}d", static_cast<int32_t>(config.volumeSwap_));
284 }
285 
CheckProductParam(InputProductConfig & productConfig) const286 void KeyEventNormalize::CheckProductParam(InputProductConfig &productConfig) const
287 {
288     if (productConfig.volumeSwap_ != VolumeSwapConfig::NO_CONFIG) {
289         return;
290     }
291     const std::string theProduct { "UNKNOWN_PRODUCT" };
292     std::string product = OHOS::system::GetParameter("const.build.product", "");
293     if (product == theProduct) {
294         productConfig.volumeSwap_ = VolumeSwapConfig::SWAP_ON_FOLD;
295     } else {
296         productConfig.volumeSwap_ = VolumeSwapConfig::NO_VOLUME_SWAP;
297     }
298 }
299 
TransformVolumeKey(struct libinput_device * dev,int32_t keyCode,int32_t keyAction) const300 int32_t KeyEventNormalize::TransformVolumeKey(struct libinput_device *dev, int32_t keyCode, int32_t keyAction) const
301 {
302     CHKPR(g_foldStatusCallback, keyCode);
303     static std::once_flag flag;
304     static std::map<int32_t, Rosen::FoldStatus> displayModes {
305         { KeyEvent::KEYCODE_VOLUME_DOWN, Rosen::FoldStatus::UNKNOWN },
306         { KeyEvent::KEYCODE_VOLUME_UP, Rosen::FoldStatus::UNKNOWN },
307     };
308     static InputProductConfig productConfig {};
309 
310     std::call_once(flag, [this]() {
311         ReadProductConfig(productConfig);
312         CheckProductParam(productConfig);
313     });
314     if (productConfig.volumeSwap_ != VolumeSwapConfig::SWAP_ON_FOLD) {
315         return keyCode;
316     }
317     auto iter = displayModes.find(keyCode);
318     if (iter == displayModes.end()) {
319         return keyCode;
320     }
321     if (keyAction == KeyEvent::KEY_ACTION_DOWN) {
322         iter->second = g_foldStatusCallback->GetFoldStatus();
323     }
324     if (iter->second != Rosen::FoldStatus::FOLDED) {
325         return keyCode;
326     }
327     const char *name = libinput_device_get_name(dev);
328     int32_t busType = static_cast<int32_t>(libinput_device_get_id_bustype(dev));
329     MMI_HILOGD("Flip volume keys upon fold: Dev:%{public}s, Bus:%{public}d",
330         name != nullptr ? name : "(null)", busType);
331     if (busType != BUS_HOST) {
332         return keyCode;
333     }
334     return (keyCode == KeyEvent::KEYCODE_VOLUME_DOWN ? KeyEvent::KEYCODE_VOLUME_UP : KeyEvent::KEYCODE_VOLUME_DOWN);
335 }
336 } // namespace MMI
337 } // namespace OHOS
338