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