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