/* * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "key_command_handler.h" #include "ability_manager_client.h" #include "bytrace_adapter.h" #include "cJSON.h" #include "config_policy_utils.h" #include "define_multimodal.h" #include "dfx_hisysevent.h" #include "error_multimodal.h" #include "file_ex.h" #include "input_event_data_transformation.h" #include "input_event_handler.h" #include "mmi_log.h" #include "net_packet.h" #include "proto.h" #include "timer_manager.h" #include "util_ex.h" namespace OHOS { namespace MMI { namespace { constexpr int32_t MAX_PREKEYS_NUM = 4; constexpr int32_t MAX_SEQUENCEKEYS_NUM = 10; constexpr int64_t MAX_DELAY_TIME = 1000000; constexpr int64_t SECONDS_SYSTEM = 1000; constexpr int32_t SPECIAL_KEY_DOWN_DELAY = 150; constexpr int32_t MAX_SHORT_KEY_DOWN_DURATION = 4000; constexpr int32_t MIN_SHORT_KEY_DOWN_DURATION = 0; constexpr int32_t ERROR_DELAY_VALUE = -1000; constexpr int32_t TOUCH_MAX_THRESHOLD = 15; constexpr int32_t COMMON_PARAMETER_ERROR = 401; constexpr size_t SINGEL_KNUCKLE_SIZE = 1; constexpr size_t DOUBLE_KNUCKLE_SIZE = 2; constexpr int32_t NONE_CLICK_STATE = 0; constexpr int32_t CLICK_STATE = 1; constexpr int32_t DOUBLE_CLICK_INTERVAL_TIME = 260; constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "KeyCommandHandler" }; const std::string shortKeyFileName = "/data/service/el1/public/multimodalinput/Settings.xml"; const std::string SINGLE_KNUCKLE_ABILITY = "SingleKnuckleDoubleClickGesture"; const std::string DOUBLE_KNUCKLE_ABILITY = "DoubleKnuckleDoubleClickGesture"; enum SpecialType { SPECIAL_ALL = 0, SUBSCRIBER_BEFORE_DELAY = 1, KEY_DOWN_ACTION = 2 }; const std::map SPECIAL_KEYS = { { KeyEvent::KEYCODE_POWER, SpecialType::KEY_DOWN_ACTION }, { KeyEvent::KEYCODE_VOLUME_DOWN, SpecialType::SPECIAL_ALL }, { KeyEvent::KEYCODE_VOLUME_UP, SpecialType::SPECIAL_ALL } }; struct JsonParser { JsonParser() = default; ~JsonParser() { if (json_ != nullptr) { cJSON_Delete(json_); } } operator cJSON *() { return json_; } cJSON *json_ { nullptr }; }; bool IsSpecialType(int32_t keyCode, SpecialType type) { auto it = SPECIAL_KEYS.find(keyCode); if (it == SPECIAL_KEYS.end()) { return false; } return (it->second == SpecialType::SPECIAL_ALL || it->second == type); } bool GetBusinessId(const cJSON* jsonData, std::string &businessIdValue, std::vector &businessIds) { if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("jsonData is not object"); return false; } cJSON *businessId = cJSON_GetObjectItemCaseSensitive(jsonData, "businessId"); if (!cJSON_IsString(businessId)) { MMI_HILOGE("businessId is not string"); return false; } businessIdValue = businessId->valuestring; businessIds.push_back(businessIdValue); return true; } bool GetPreKeys(const cJSON* jsonData, ShortcutKey &shortcutKey) { if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("jsonData is not object"); return false; } cJSON* preKey = cJSON_GetObjectItemCaseSensitive(jsonData, "preKey"); if (!cJSON_IsArray(preKey)) { MMI_HILOGE("preKey number must be array"); return false; } int32_t preKeySize = cJSON_GetArraySize(preKey); if (preKeySize > MAX_PREKEYS_NUM) { MMI_HILOGE("preKeySize number must less and equal four"); return false; } for (int32_t i = 0; i < preKeySize; ++i) { cJSON *preKeyJson = cJSON_GetArrayItem(preKey, i); if (!cJSON_IsNumber(preKeyJson)) { MMI_HILOGE("preKeyJson is not number"); return false; } if (preKeyJson->valueint < 0) { MMI_HILOGE("preKeyJson must be number and bigger or equal than 0"); return false; } if (!shortcutKey.preKeys.emplace(preKeyJson->valueint).second) { MMI_HILOGE("preKeyJson must be unduplicated"); return false; } } return true; } bool GetTrigger(const cJSON* jsonData, int32_t &triggerType) { if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("jsonData is not object"); return false; } cJSON *trigger = cJSON_GetObjectItemCaseSensitive(jsonData, "trigger"); if (!cJSON_IsString(trigger)) { MMI_HILOGE("trigger is not string"); return false; } if (((std::strcmp(trigger->valuestring, "key_up") != 0) && (std::strcmp(trigger->valuestring, "key_down") != 0))) { MMI_HILOGE("trigger must be one of [key_up, key_down]"); return false; } if (std::strcmp(trigger->valuestring, "key_up") == 0) { triggerType = KeyEvent::KEY_ACTION_UP; } else { triggerType = KeyEvent::KEY_ACTION_DOWN; } return true; } bool GetKeyDownDuration(const cJSON* jsonData, int32_t &keyDownDurationInt) { if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("jsonData is not object"); return false; } cJSON *keyDownDuration = cJSON_GetObjectItemCaseSensitive(jsonData, "keyDownDuration"); if (!cJSON_IsNumber(keyDownDuration)) { MMI_HILOGE("keyDownDuration is not number"); return false; } if (keyDownDuration->valueint < 0) { MMI_HILOGE("keyDownDuration must be number and bigger and equal zero"); return false; } keyDownDurationInt = keyDownDuration->valueint; return true; } bool GetKeyFinalKey(const cJSON* jsonData, int32_t &finalKeyInt) { if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("jsonData is not object"); return false; } cJSON *finalKey = cJSON_GetObjectItemCaseSensitive(jsonData, "finalKey"); if (!cJSON_IsNumber(finalKey)) { MMI_HILOGE("finalKey must be number"); return false; } finalKeyInt = finalKey->valueint; return true; } void GetKeyVal(const cJSON* json, const std::string &key, std::string &value) { if (!cJSON_IsObject(json)) { MMI_HILOGE("json is not object"); return; } cJSON *valueJson = cJSON_GetObjectItemCaseSensitive(json, key.c_str()); if (cJSON_IsString(valueJson)) { value = valueJson->valuestring; } return; } bool GetEntities(const cJSON* jsonAbility, Ability &ability) { if (!cJSON_IsObject(jsonAbility)) { MMI_HILOGE("jsonAbility is not object"); return false; } cJSON *entities = cJSON_GetObjectItemCaseSensitive(jsonAbility, "entities"); if (entities == nullptr) { return true; } if (!cJSON_IsArray(entities)) { MMI_HILOGE("entities must be array"); return false; } int32_t entitySize = cJSON_GetArraySize(entities); for (int32_t i = 0; i < entitySize; i++) { cJSON* entity = cJSON_GetArrayItem(entities, i); if (!cJSON_IsString(entity)) { MMI_HILOGE("entity is not string"); return false; } ability.entities.push_back(entity->valuestring); } return true; } bool GetParams(const cJSON* jsonAbility, Ability &ability) { if (!cJSON_IsObject(jsonAbility)) { MMI_HILOGE("jsonAbility is not object"); return false; } cJSON *params = cJSON_GetObjectItemCaseSensitive(jsonAbility, "params"); if (params == nullptr) { return true; } if (!cJSON_IsArray(params)) { MMI_HILOGE("params must be array"); return false; } int32_t paramsSize = cJSON_GetArraySize(params); for (int32_t i = 0; i < paramsSize; ++i) { cJSON* param = cJSON_GetArrayItem(params, i); if (!cJSON_IsObject(param)) { MMI_HILOGE("param must be object"); return false; } cJSON* key = cJSON_GetObjectItemCaseSensitive(param, "key"); if (!cJSON_IsString(key)) { MMI_HILOGE("key is not string"); return false; } cJSON* value = cJSON_GetObjectItemCaseSensitive(param, "value"); if (!cJSON_IsString(value)) { MMI_HILOGE("value is not string"); return false; } auto ret = ability.params.emplace(key->valuestring, value->valuestring); if (!ret.second) { MMI_HILOGW("Emplace to failed"); } } return true; } bool PackageAbility(const cJSON* jsonAbility, Ability &ability) { if (!cJSON_IsObject(jsonAbility)) { MMI_HILOGE("JsonAbility is not object"); return false; } GetKeyVal(jsonAbility, "bundleName", ability.bundleName); GetKeyVal(jsonAbility, "abilityName", ability.abilityName); GetKeyVal(jsonAbility, "action", ability.action); GetKeyVal(jsonAbility, "type", ability.type); GetKeyVal(jsonAbility, "deviceId", ability.deviceId); GetKeyVal(jsonAbility, "uri", ability.uri); if (!GetEntities(jsonAbility, ability)) { MMI_HILOGE("Get centities failed"); return false; } if (!GetParams(jsonAbility, ability)) { MMI_HILOGE("Get params failed"); return false; } return true; } bool ConvertToShortcutKey(const cJSON* jsonData, ShortcutKey &shortcutKey, std::vector &businessIds) { if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("jsonData is not object"); return false; } if (!GetBusinessId(jsonData, shortcutKey.businessId, businessIds)) { MMI_HILOGW("Get abilityKey failed"); } if (!GetPreKeys(jsonData, shortcutKey)) { MMI_HILOGE("Get preKeys failed"); return false; } if (!GetKeyFinalKey(jsonData, shortcutKey.finalKey)) { MMI_HILOGE("Get finalKey failed"); return false; } if (!GetTrigger(jsonData, shortcutKey.triggerType)) { MMI_HILOGE("Get trigger failed"); return false; } if (!GetKeyDownDuration(jsonData, shortcutKey.keyDownDuration)) { MMI_HILOGE("Get downDuration failed"); return false; } cJSON *ability = cJSON_GetObjectItemCaseSensitive(jsonData, "ability"); if (!cJSON_IsObject(ability)) { MMI_HILOGE("ability is not object"); return false; } if (!PackageAbility(ability, shortcutKey.ability)) { MMI_HILOGE("Package ability failed"); return false; } return true; } bool GetKeyCode(const cJSON* jsonData, int32_t &keyCodeInt) { if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("jsonData is not object"); return false; } cJSON *keyCode = cJSON_GetObjectItemCaseSensitive(jsonData, "keyCode"); if (!cJSON_IsNumber(keyCode)) { MMI_HILOGE("keyCode is not number"); return false; } if (keyCode->valueint < 0) { MMI_HILOGE("keyCode must be number and bigger and equal zero"); return false; } keyCodeInt = keyCode->valueint; return true; } bool GetKeyAction(const cJSON* jsonData, int32_t &keyActionInt) { if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("jsonData is not object"); return false; } cJSON *keyAction = cJSON_GetObjectItemCaseSensitive(jsonData, "keyAction"); if (!cJSON_IsNumber(keyAction)) { MMI_HILOGE("keyAction is not number"); return false; } if ((keyAction->valueint != KeyEvent::KEY_ACTION_DOWN) && (keyAction->valueint != KeyEvent::KEY_ACTION_UP)) { MMI_HILOGE("keyAction must be down or up"); return false; } keyActionInt = keyAction->valueint; return true; } bool GetDelay(const cJSON* jsonData, int64_t &delayInt) { if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("jsonData is not object"); return false; } cJSON *delay = cJSON_GetObjectItemCaseSensitive(jsonData, "delay"); if (!cJSON_IsNumber(delay)) { MMI_HILOGE("delay is not number"); return false; } if ((delay->valueint < 0) || (delay->valueint > MAX_DELAY_TIME)) { MMI_HILOGE("delay must be number and bigger and equal zero and less than max delay"); return false; } delayInt = delay->valueint * SECONDS_SYSTEM; return true; } bool GetAbilityStartDelay(const cJSON* jsonData, int64_t &abilityStartDelayInt) { if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("jsonData is not object"); return false; } cJSON *abilityStartDelay = cJSON_GetObjectItemCaseSensitive(jsonData, "abilityStartDelay"); if (!cJSON_IsNumber(abilityStartDelay)) { MMI_HILOGE("abilityStartDelay is not number"); return false; } if ((abilityStartDelay->valueint < 0) || (abilityStartDelay->valueint > MAX_DELAY_TIME)) { MMI_HILOGE("abilityStartDelay must be number and bigger and equal zero and less than max delay time"); return false; } abilityStartDelayInt = abilityStartDelay->valueint; return true; } bool PackageSequenceKey(const cJSON* sequenceKeysJson, SequenceKey &sequenceKey) { if (!cJSON_IsObject(sequenceKeysJson)) { MMI_HILOGE("sequenceKeysJson is not object"); return false; } if (!GetKeyCode(sequenceKeysJson, sequenceKey.keyCode)) { MMI_HILOGE("Get keyCode failed"); return false; } if (!GetKeyAction(sequenceKeysJson, sequenceKey.keyAction)) { MMI_HILOGE("Get keyAction failed"); return false; } if (!GetDelay(sequenceKeysJson, sequenceKey.delay)) { MMI_HILOGE("Get delay failed"); return false; } return true; } bool GetSequenceKeys(const cJSON* jsonData, Sequence &sequence) { if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("jsonData is not object"); return false; } cJSON* sequenceKeys = cJSON_GetObjectItemCaseSensitive(jsonData, "sequenceKeys"); if (!cJSON_IsArray(sequenceKeys)) { MMI_HILOGE("sequenceKeys number must be array"); return false; } int32_t sequenceKeysSize = cJSON_GetArraySize(sequenceKeys); if (sequenceKeysSize > MAX_SEQUENCEKEYS_NUM) { MMI_HILOGE("sequenceKeysSize number must less and equal %{public}d", MAX_SEQUENCEKEYS_NUM); return false; } for (int32_t i = 0; i < sequenceKeysSize; ++i) { cJSON *sequenceKeysJson = cJSON_GetArrayItem(sequenceKeys, i); if (!cJSON_IsObject(sequenceKeysJson)) { MMI_HILOGE("sequenceKeysJson is not object"); return false; } SequenceKey sequenceKey; if (!PackageSequenceKey(sequenceKeysJson, sequenceKey)) { MMI_HILOGE("Packege sequenceKey failed"); return false; } sequence.sequenceKeys.push_back(sequenceKey); } return true; } bool IsSequenceKeysValid(const Sequence &sequence) { if (sequence.sequenceKeys.empty()) { MMI_HILOGE("sequenceKeys can not be empty"); return false; } if (sequence.sequenceKeys.size() > MAX_SEQUENCEKEYS_NUM) { MMI_HILOGE("sequenceKeys size must less or equal to %{public}d", MAX_SEQUENCEKEYS_NUM); return false; } std::map sequenceKeys; for (const SequenceKey& item : sequence.sequenceKeys) { if (sequenceKeys.find(item.keyCode) == sequenceKeys.end()) { auto it = sequenceKeys.emplace(item.keyCode, item); if (!it.second) { MMI_HILOGE("Emplace duplicated"); return false; } } else { if (sequenceKeys[item.keyCode].keyAction == item.keyAction) { MMI_HILOGE("sequenceKeys illegal"); return false; } sequenceKeys[item.keyCode].keyAction = item.keyAction; sequenceKeys[item.keyCode].delay = item.delay; } } return true; } bool ConvertToKeySequence(const cJSON* jsonData, Sequence &sequence) { if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("jsonData is not object"); return false; } if (!GetSequenceKeys(jsonData, sequence)) { MMI_HILOGE("Get sequenceKeys failed"); return false; } if (!IsSequenceKeysValid(sequence)) { MMI_HILOGE("Sequence invalid"); return false; } if (!GetAbilityStartDelay(jsonData, sequence.abilityStartDelay)) { MMI_HILOGE("Get abilityStartDelay failed"); return false; } cJSON *ability = cJSON_GetObjectItemCaseSensitive(jsonData, "ability"); if (!cJSON_IsObject(ability)) { MMI_HILOGE("ability is not object"); return false; } if (!PackageAbility(ability, sequence.ability)) { MMI_HILOGE("Package ability failed"); return false; } return true; } std::string GenerateKey(const ShortcutKey& key) { std::set preKeys = key.preKeys; std::stringstream ss; for (const auto& preKey : preKeys) { ss << preKey << ","; } ss << key.finalKey << ","; ss << key.triggerType; return std::string(ss.str()); } bool ParseShortcutKeys(const JsonParser& parser, std::map& shortcutKeyMap, std::vector& businessIds) { cJSON* shortkeys = cJSON_GetObjectItemCaseSensitive(parser.json_, "Shortkeys"); if (!cJSON_IsArray(shortkeys)) { MMI_HILOGE("shortkeys is not array"); return false; } int32_t shortkeysSize = cJSON_GetArraySize(shortkeys); for (int32_t i = 0; i < shortkeysSize; ++i) { ShortcutKey shortcutKey; cJSON *shortkey = cJSON_GetArrayItem(shortkeys, i); if (!cJSON_IsObject(shortkey)) { continue; } if (!ConvertToShortcutKey(shortkey, shortcutKey, businessIds)) { continue; } std::string key = GenerateKey(shortcutKey); if (shortcutKeyMap.find(key) == shortcutKeyMap.end()) { if (!shortcutKeyMap.emplace(key, shortcutKey).second) { MMI_HILOGW("Duplicate shortcutKey:%{public}s", key.c_str()); } } } return true; } bool ParseSequences(const JsonParser& parser, std::vector& sequenceVec) { cJSON* sequences = cJSON_GetObjectItemCaseSensitive(parser.json_, "Sequences"); if (!cJSON_IsArray(sequences)) { MMI_HILOGE("sequences is not array"); return false; } int32_t sequencesSize = cJSON_GetArraySize(sequences); for (int32_t i = 0; i < sequencesSize; ++i) { Sequence seq; cJSON *sequence = cJSON_GetArrayItem(sequences, i); if (!cJSON_IsObject(sequence)) { continue; } if (!ConvertToKeySequence(sequence, seq)) { continue; } sequenceVec.push_back(seq); } return true; } bool ParseTwoFingerGesture(const JsonParser& parser, TwoFingerGesture& gesture) { cJSON *jsonData = cJSON_GetObjectItemCaseSensitive(parser.json_, "TwoFingerGesture"); if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("TwoFingerGesture is not object"); return false; } if (!GetAbilityStartDelay(jsonData, gesture.abilityStartDelay)) { MMI_HILOGE("Get abilityStartDelay failed"); return false; } cJSON *ability = cJSON_GetObjectItemCaseSensitive(jsonData, "ability"); if (!cJSON_IsObject(ability)) { MMI_HILOGE("ability is not object"); return false; } if (!PackageAbility(ability, gesture.ability)) { MMI_HILOGE("Package ability failed"); return false; } gesture.active = true; return true; } bool IsPackageKnuckleGesture(const cJSON* jsonData, const std::string knuckleGesture, Ability &launchAbility) { cJSON *knuckleGestureData = cJSON_GetObjectItemCaseSensitive(jsonData, knuckleGesture.c_str()); if (!cJSON_IsObject(knuckleGestureData)) { MMI_HILOGE("KnuckleGestureData is not object"); return false; } cJSON *ability = cJSON_GetObjectItemCaseSensitive(knuckleGestureData, "ability"); if (!cJSON_IsObject(ability)) { MMI_HILOGE("Ability is not object"); return false; } if (!PackageAbility(ability, launchAbility)) { MMI_HILOGE("Package ability failed"); return false; } return true; } bool IsParseKnuckleGesture(const JsonParser &parser, const std::string ability, KnuckleGesture &knuckleGesture) { cJSON *jsonData = cJSON_GetObjectItemCaseSensitive(parser.json_, "KnuckleGesture"); if (!cJSON_IsObject(jsonData)) { MMI_HILOGE("KnuckleGesture is not object"); return false; } if (!IsPackageKnuckleGesture(jsonData, ability, knuckleGesture.ability)) { MMI_HILOGE("Package knuckle gesture failed"); return false; } return true; } } // namespace #ifdef OHOS_BUILD_ENABLE_KEYBOARD void KeyCommandHandler::HandleKeyEvent(const std::shared_ptr keyEvent) { CHKPV(keyEvent); if (OnHandleEvent(keyEvent)) { MMI_HILOGD("The keyEvent start launch an ability, keyCode:%{public}d", keyEvent->GetKeyCode()); BytraceAdapter::StartBytrace(keyEvent, BytraceAdapter::KEY_LAUNCH_EVENT); return; } CHKPV(nextHandler_); nextHandler_->HandleKeyEvent(keyEvent); } #endif // OHOS_BUILD_ENABLE_KEYBOARD #ifdef OHOS_BUILD_ENABLE_POINTER void KeyCommandHandler::HandlePointerEvent(const std::shared_ptr pointerEvent) { CHKPV(pointerEvent); CHKPV(nextHandler_); nextHandler_->HandlePointerEvent(pointerEvent); } #endif // OHOS_BUILD_ENABLE_POINTER #ifdef OHOS_BUILD_ENABLE_TOUCH void KeyCommandHandler::HandleTouchEvent(const std::shared_ptr pointerEvent) { CHKPV(pointerEvent); CHKPV(nextHandler_); OnHandleTouchEvent(pointerEvent); if (isKnuckleState_) { MMI_HILOGD("current pointer event is knuckle"); return; } nextHandler_->HandleTouchEvent(pointerEvent); } void KeyCommandHandler::OnHandleTouchEvent(const std::shared_ptr &touchEvent) { CALL_DEBUG_ENTER; CHKPV(touchEvent); if (!isParseConfig_) { if (!ParseConfig()) { MMI_HILOGE("Parse configFile failed"); return; } isParseConfig_ = true; } switch (touchEvent->GetPointerAction()) { case PointerEvent::POINTER_ACTION_CANCEL: case PointerEvent::POINTER_ACTION_UP: { HandlePointerActionUpEvent(touchEvent); break; } case PointerEvent::POINTER_ACTION_MOVE: { HandlePointerActionMoveEvent(touchEvent); break; } case PointerEvent::POINTER_ACTION_DOWN: { HandlePointerActionDownEvent(touchEvent); break; } default: // Don't care about other actions MMI_HILOGW("other action not match."); break; } } void KeyCommandHandler::HandlePointerActionDownEvent(const std::shared_ptr &touchEvent) { CALL_DEBUG_ENTER; CHKPV(touchEvent); auto id = touchEvent->GetPointerId(); PointerEvent::PointerItem item; touchEvent->GetPointerItem(id, item); int32_t toolType = item.GetToolType(); MMI_HILOGD("Pointer tool type: %{public}d", toolType); switch (toolType) { case PointerEvent::TOOL_TYPE_FINGER: { isKnuckleState_ = false; HandleFingerGestureDownEvent(touchEvent); break; } case PointerEvent::TOOL_TYPE_KNUCKLE: { HandleKnuckleGestureDownEvent(touchEvent); break; } default: { // other tool type are not processed isKnuckleState_ = false; MMI_HILOGD("Current touch event tool type: %{public}d", toolType); break; } } } void KeyCommandHandler::HandlePointerActionMoveEvent(const std::shared_ptr &touchEvent) { CALL_DEBUG_ENTER; if (!twoFingerGesture_.active) { return; } if (twoFingerGesture_.timerId == -1) { MMI_HILOGW("Two finger gesture timer id is -1."); return; } auto id = touchEvent->GetPointerId(); auto pos = std::find_if(std::begin(twoFingerGesture_.touches), std::end(twoFingerGesture_.touches), [id](const auto& item) { return item.id == id; }); if (pos == std::end(twoFingerGesture_.touches)) { return; } PointerEvent::PointerItem item; touchEvent->GetPointerItem(id, item); auto dx = std::abs(pos->x - item.GetDisplayX()); auto dy = std::abs(pos->y - item.GetDisplayY()); if (dx > TOUCH_MAX_THRESHOLD || dy > TOUCH_MAX_THRESHOLD) { StopTwoFingerGesture(); } } void KeyCommandHandler::HandlePointerActionUpEvent(const std::shared_ptr &touchEvent) { CALL_DEBUG_ENTER; CHKPV(touchEvent); auto id = touchEvent->GetPointerId(); PointerEvent::PointerItem item; touchEvent->GetPointerItem(id, item); int32_t toolType = item.GetToolType(); switch (toolType) { case PointerEvent::TOOL_TYPE_FINGER: { HandleFingerGestureUpEvent(touchEvent); break; } case PointerEvent::TOOL_TYPE_KNUCKLE: { HandleKnuckleGestureUpEvent(touchEvent); break; } default: { // other tool type are not processed MMI_HILOGW("Current touch event tool type: %{public}d", toolType); break; } } } void KeyCommandHandler::HandleFingerGestureDownEvent(const std::shared_ptr &touchEvent) { CALL_DEBUG_ENTER; if (!twoFingerGesture_.active) { MMI_HILOGD("Two finger gesture is not active"); return; } auto num = touchEvent->GetPointerIds().size(); if (num == TwoFingerGesture::MAX_TOUCH_NUM) { StartTwoFingerGesture(); } else { StopTwoFingerGesture(); } if (num > 0 && num <= TwoFingerGesture::MAX_TOUCH_NUM) { auto id = touchEvent->GetPointerId(); PointerEvent::PointerItem item; touchEvent->GetPointerItem(id, item); twoFingerGesture_.touches[num - 1].id = id; twoFingerGesture_.touches[num - 1].x = item.GetDisplayX(); twoFingerGesture_.touches[num - 1].y = item.GetDisplayY(); } } void KeyCommandHandler::HandleFingerGestureUpEvent(const std::shared_ptr &touchEvent) { CALL_DEBUG_ENTER; CHKPV(touchEvent); if (!twoFingerGesture_.active) { MMI_HILOGD("Two finger gesture is not active"); return; } StopTwoFingerGesture(); } void KeyCommandHandler::HandleKnuckleGestureDownEvent(const std::shared_ptr &touchEvent) { CALL_DEBUG_ENTER; CHKPV(touchEvent); auto id = touchEvent->GetPointerId(); PointerEvent::PointerItem item; touchEvent->GetPointerItem(id, item); if (item.GetToolType() != PointerEvent::TOOL_TYPE_KNUCKLE) { MMI_HILOGW("Touch event tool type: %{public}d not knuckle", item.GetToolType()); return; } size_t size = touchEvent->GetPointerIds().size(); if (size == SINGEL_KNUCKLE_SIZE) { SingleKnuckleGestureProcesser(touchEvent); } else if (size == DOUBLE_KNUCKLE_SIZE) { DoubleKnuckleGestureProcesser(touchEvent); } else { MMI_HILOGW("Other kunckle size not process, size: %{public}zu", size); return; } } void KeyCommandHandler::HandleKnuckleGestureUpEvent(const std::shared_ptr &touchEvent) { CALL_DEBUG_ENTER; CHKPV(touchEvent); size_t size = touchEvent->GetPointerIds().size(); if (size == SINGEL_KNUCKLE_SIZE) { singleKnuckleGesture_.lastPointerUpTime = touchEvent->GetActionTime(); } else if (size == DOUBLE_KNUCKLE_SIZE) { doubleKnuckleGesture_.lastPointerUpTime = touchEvent->GetActionTime(); } else { MMI_HILOGW("Other kunckle size not process, size: %{public}zu", size); return; } } void KeyCommandHandler::SingleKnuckleGestureProcesser(const std::shared_ptr &touchEvent) { CALL_DEBUG_ENTER; CHKPV(touchEvent); KnuckleGestureProcesser(touchEvent, singleKnuckleGesture_); } void KeyCommandHandler::DoubleKnuckleGestureProcesser(const std::shared_ptr &touchEvent) { CALL_DEBUG_ENTER; CHKPV(touchEvent); if (singleKnuckleGesture_.state != NONE_CLICK_STATE) { MMI_HILOGD("Single knuckle gesture not process"); singleKnuckleGesture_.state = NONE_CLICK_STATE; if (singleKnuckleGesture_.timerId != -1) { TimerMgr->RemoveTimer(singleKnuckleGesture_.timerId); singleKnuckleGesture_.timerId = -1; } } KnuckleGestureProcesser(touchEvent, doubleKnuckleGesture_); } void KeyCommandHandler::KnuckleGestureProcesser(const std::shared_ptr &touchEvent, KnuckleGesture &knuckleGesture) { CALL_DEBUG_ENTER; CHKPV(touchEvent); int32_t state = knuckleGesture.state; switch (state) { case NONE_CLICK_STATE: { MMI_HILOGD("Knuckle gesture first down event"); knuckleGesture.timerId = TimerMgr->AddTimer(DOUBLE_CLICK_INTERVAL_TIME, 1, [&knuckleGesture]() { MMI_HILOGD("Knuckle gesture processor timer callback"); knuckleGesture.timerId = -1; knuckleGesture.state = NONE_CLICK_STATE; }); knuckleGesture.lastPointerDownEvent = touchEvent; knuckleGesture.state = CLICK_STATE; isKnuckleState_ = true; break; } case CLICK_STATE: { MMI_HILOGD("Knuckle gesture second down event"); knuckleGesture.downToPrevUpTime = touchEvent->GetActionTime() - knuckleGesture.lastPointerUpTime; if (knuckleGesture.downToPrevUpTime < (static_cast(DOUBLE_CLICK_INTERVAL_TIME) * SECONDS_SYSTEM)) { MMI_HILOGD("knuckle gesture start launch ability"); LaunchAbility(knuckleGesture.ability, 0); if (knuckleGesture.timerId != -1) { TimerMgr->RemoveTimer(knuckleGesture.timerId); knuckleGesture.timerId = -1; } knuckleGesture.state = NONE_CLICK_STATE; isKnuckleState_ = true; } break; } default: { MMI_HILOGW("other state: %{public}d not process", state); break; } } } void KeyCommandHandler::StartTwoFingerGesture() { CALL_DEBUG_ENTER; twoFingerGesture_.timerId = TimerMgr->AddTimer(twoFingerGesture_.abilityStartDelay, 1, [this]() { LaunchAbility(twoFingerGesture_.ability, twoFingerGesture_.abilityStartDelay); twoFingerGesture_.timerId = -1; }); } void KeyCommandHandler::StopTwoFingerGesture() { CALL_DEBUG_ENTER; if (twoFingerGesture_.timerId != -1) { TimerMgr->RemoveTimer(twoFingerGesture_.timerId); twoFingerGesture_.timerId = -1; } } #endif // OHOS_BUILD_ENABLE_TOUCH bool KeyCommandHandler::ParseConfig() { const char *testPathSuffix = "/etc/multimodalinput/ability_launch_config.json"; char buf[MAX_PATH_LEN] = { 0 }; char *filePath = GetOneCfgFile(testPathSuffix, buf, MAX_PATH_LEN); std::string defaultConfig = "/system/etc/multimodalinput/ability_launch_config.json"; if (filePath == nullptr || filePath[0] == '\0' || strlen(filePath) > MAX_PATH_LEN) { MMI_HILOGD("Can not get customization config file"); return ParseJson(defaultConfig); } std::string customConfig = filePath; MMI_HILOGD("The configuration file path is :%{public}s", customConfig.c_str()); return ParseJson(customConfig) || ParseJson(defaultConfig); } bool KeyCommandHandler::ParseJson(const std::string &configFile) { CALL_DEBUG_ENTER; std::string jsonStr = ReadJsonFile(configFile); if (jsonStr.empty()) { MMI_HILOGE("Read configFile failed"); return false; } JsonParser parser; parser.json_ = cJSON_Parse(jsonStr.c_str()); if (!cJSON_IsObject(parser.json_)) { MMI_HILOGE("Parser.json_ is not object"); return false; } bool isParseShortKeys = ParseShortcutKeys(parser, shortcutKeys_, businessIds_); bool isParseSequences = ParseSequences(parser, sequences_); bool isParseTwoFingerGesture = ParseTwoFingerGesture(parser, twoFingerGesture_); bool isParseSingleKnuckleGesture = IsParseKnuckleGesture(parser, SINGLE_KNUCKLE_ABILITY, singleKnuckleGesture_); bool isParseDoubleKnuckleGesture = IsParseKnuckleGesture(parser, DOUBLE_KNUCKLE_ABILITY, doubleKnuckleGesture_); if (!isParseShortKeys && !isParseSequences && !isParseTwoFingerGesture && !isParseSingleKnuckleGesture && !isParseDoubleKnuckleGesture) { MMI_HILOGE("Parse configFile failed"); return false; } Print(); PrintSeq(); return true; } void KeyCommandHandler::Print() { MMI_HILOGD("shortcutKey count:%{public}zu", shortcutKeys_.size()); int32_t row = 0; for (const auto &item : shortcutKeys_) { MMI_HILOGD("row:%{public}d", row++); auto &shortcutKey = item.second; for (const auto &prekey : shortcutKey.preKeys) { MMI_HILOGD("preKey:%{public}d", prekey); } MMI_HILOGD("finalKey:%{public}d, keyDownDuration:%{public}d, triggerType:%{public}d," " bundleName:%{public}s, abilityName:%{public}s", shortcutKey.finalKey, shortcutKey.keyDownDuration, shortcutKey.triggerType, shortcutKey.ability.bundleName.c_str(), shortcutKey.ability.abilityName.c_str()); } } void KeyCommandHandler::PrintSeq() { MMI_HILOGD("sequences count:%{public}zu", sequences_.size()); int32_t row = 0; for (const auto &item : sequences_) { MMI_HILOGD("row:%{public}d", row++); for (const auto& sequenceKey : item.sequenceKeys) { MMI_HILOGD("keyCode:%{public}d, keyAction:%{public}d, delay:%{public}" PRId64, sequenceKey.keyCode, sequenceKey.keyAction, sequenceKey.delay); } MMI_HILOGD("bundleName:%{public}s, abilityName:%{public}s", item.ability.bundleName.c_str(), item.ability.abilityName.c_str()); } } bool KeyCommandHandler::OnHandleEvent(const std::shared_ptr key) { CALL_DEBUG_ENTER; CHKPF(key); if (!isParseConfig_) { if (!ParseConfig()) { MMI_HILOGE("Parse configFile failed"); return false; } isParseConfig_ = true; } bool isHandled = HandleShortKeys(key); isHandled = HandleSequences(key) || isHandled; if (isHandled) { return true; } if (!specialKeys_.empty() && specialKeys_.find(key->GetKeyCode()) != specialKeys_.end()) { HandleSpecialKeys(key->GetKeyCode(), key->GetAction()); return true; } if (IsSpecialType(key->GetKeyCode(), SpecialType::SUBSCRIBER_BEFORE_DELAY)) { auto tmpKey = KeyEvent::Clone(key); int32_t timerId = TimerMgr->AddTimer(SPECIAL_KEY_DOWN_DELAY, 1, [this, tmpKey] () { MMI_HILOGD("Timer callback"); auto it = specialTimers_.find(tmpKey->GetKeyCode()); if (it != specialTimers_.end() && !it->second.empty()) { it->second.pop_front(); } InputHandler->GetSubscriberHandler()->HandleKeyEvent(tmpKey); }); if (timerId < 0) { MMI_HILOGE("Add timer failed"); return false; } auto it = specialTimers_.find(key->GetKeyCode()); if (it == specialTimers_.end()) { std::list timerIds; timerIds.push_back(timerId); auto it = specialTimers_.emplace(key->GetKeyCode(), timerIds); if (!it.second) { MMI_HILOGE("Keycode duplicated"); return false; } } else { it->second.push_back(timerId); } MMI_HILOGD("Add timer success"); return true; } return false; } bool KeyCommandHandler::HandleShortKeys(const std::shared_ptr keyEvent) { CALL_DEBUG_ENTER; CHKPF(keyEvent); if (shortcutKeys_.empty()) { MMI_HILOGD("No shortkeys configuration data"); return false; } if (IsKeyMatch(lastMatchedKey_, keyEvent)) { MMI_HILOGD("The same key is waiting timeout, skip"); return true; } if (currentLaunchAbilityKey_.timerId >= 0 && IsKeyMatch(currentLaunchAbilityKey_, keyEvent)) { MMI_HILOGD("repeat, current key %{public}d has launched ability", currentLaunchAbilityKey_.finalKey); return true; } DfxHisysevent::GetComboStartTime(); if (lastMatchedKey_.timerId >= 0) { MMI_HILOGD("Remove timer:%{public}d", lastMatchedKey_.timerId); TimerMgr->RemoveTimer(lastMatchedKey_.timerId); } ResetLastMatchedKey(); for (auto &item : shortcutKeys_) { ShortcutKey &shortcutKey = item.second; if (!IsKeyMatch(shortcutKey, keyEvent)) { MMI_HILOGD("Not key matched, next"); continue; } int32_t delay = GetKeyDownDurationFromXml(shortcutKey.businessId); if (delay >= MIN_SHORT_KEY_DOWN_DURATION && delay <= MAX_SHORT_KEY_DOWN_DURATION) { MMI_HILOGD("User defined new short key down duration: %{public}d", delay); shortcutKey.keyDownDuration = delay; } shortcutKey.Print(); if (shortcutKey.triggerType == KeyEvent::KEY_ACTION_DOWN) { return HandleKeyDown(shortcutKey); } else if (shortcutKey.triggerType == KeyEvent::KEY_ACTION_UP) { return HandleKeyUp(keyEvent, shortcutKey); } else { return HandleKeyCancel(shortcutKey); } } return HandleConsumedKeyEvent(keyEvent); } bool KeyCommandHandler::HandleConsumedKeyEvent(const std::shared_ptr keyEvent) { CALL_DEBUG_ENTER; CHKPF(keyEvent); if (currentLaunchAbilityKey_.finalKey == keyEvent->GetKeyCode() && keyEvent->GetKeyAction() == KeyEvent::KEY_ACTION_UP) { MMI_HILOGD("Handle consumed key event, cancel opration"); ResetCurrentLaunchAbilityKey(); auto keyEventCancel = std::make_shared(*keyEvent); keyEventCancel->SetKeyAction(KeyEvent::KEY_ACTION_CANCEL); auto inputEventNormalizeHandler = InputHandler->GetEventNormalizeHandler(); CHKPF(inputEventNormalizeHandler); inputEventNormalizeHandler->HandleKeyEvent(keyEventCancel); return true; } return false; } bool KeyCommandHandler::IsRepeatKeyEvent(const SequenceKey &sequenceKey) { for (size_t i = keys_.size(); i > 0; --i) { if (keys_[i-1].keyCode == sequenceKey.keyCode) { if (keys_[i-1].keyAction == sequenceKey.keyAction) { MMI_HILOGD("Is repeat key, keyCode:%{public}d", sequenceKey.keyCode); return true; } MMI_HILOGD("Is not repeat key"); return false; } } return false; } bool KeyCommandHandler::HandleSequences(const std::shared_ptr keyEvent) { CALL_DEBUG_ENTER; CHKPF(keyEvent); if (sequences_.empty()) { MMI_HILOGD("No sequences configuration data"); return false; } if (!AddSequenceKey(keyEvent)) { MMI_HILOGD("Add new sequence key failed"); return false; } if (filterSequences_.empty()) { filterSequences_ = sequences_; } bool isLaunchAbility = false; std::vector tempSeqs; for (Sequence& item : filterSequences_) { if (HandleSequence(item, isLaunchAbility)) { tempSeqs.push_back(item); } } if (isLaunchAbility) { for (const auto& item : keys_) { if (IsSpecialType(item.keyCode, SpecialType::KEY_DOWN_ACTION)) { HandleSpecialKeys(item.keyCode, item.keyAction); } InputHandler->GetSubscriberHandler()->RemoveSubscriberKeyUpTimer(item.keyCode); RemoveSubscribedTimer(item.keyCode); } } if (tempSeqs.empty()) { MMI_HILOGD("No matching sequence found"); } else { filterSequences_ = tempSeqs; } return isLaunchAbility; } bool KeyCommandHandler::AddSequenceKey(const std::shared_ptr keyEvent) { CALL_DEBUG_ENTER; CHKPF(keyEvent); SequenceKey sequenceKey; sequenceKey.keyCode = keyEvent->GetKeyCode(); sequenceKey.keyAction = keyEvent->GetKeyAction(); sequenceKey.actionTime = keyEvent->GetActionTime(); size_t size = keys_.size(); if (size > 0) { if (keys_[size - 1].actionTime > sequenceKey.actionTime) { MMI_HILOGE("The current event time is greater than the last event time"); ResetSequenceKeys(); return false; } if ((sequenceKey.actionTime - keys_[size - 1].actionTime) > MAX_DELAY_TIME) { MMI_HILOGD("The delay time is greater than the maximum delay time"); ResetSequenceKeys(); } else { if (IsRepeatKeyEvent(sequenceKey)) { MMI_HILOGD("This is a repeat key event, don't add"); return false; } keys_[size - 1].delay = sequenceKey.actionTime - keys_[size - 1].actionTime; InterruptTimers(); } } if (size > MAX_SEQUENCEKEYS_NUM) { MMI_HILOGD("The save key size more than the max size"); return false; } keys_.push_back(sequenceKey); return true; } bool KeyCommandHandler::HandleSequence(Sequence &sequence, bool &isLaunchAbility) { CALL_DEBUG_ENTER; size_t keysSize = keys_.size(); size_t sequenceKeysSize = sequence.sequenceKeys.size(); if (keysSize > sequenceKeysSize) { MMI_HILOGD("The save sequence not matching ability sequence"); return false; } for (size_t i = 0; i < keysSize; ++i) { if (keys_[i] != sequence.sequenceKeys[i]) { MMI_HILOGD("The keyCode or keyAction not matching"); return false; } int64_t delay = sequence.sequenceKeys[i].delay; if (((i + 1) != keysSize) && (delay != 0) && (keys_[i].delay >= delay)) { MMI_HILOGD("Delay is not matching"); return false; } } if (keysSize == sequenceKeysSize) { if (sequence.abilityStartDelay == 0) { MMI_HILOGD("Start launch ability immediately"); LaunchAbility(sequence); isLaunchAbility = true; return true; } sequence.timerId = TimerMgr->AddTimer(sequence.abilityStartDelay, 1, [this, sequence] () { MMI_HILOGD("Timer callback"); LaunchAbility(sequence); }); if (sequence.timerId < 0) { MMI_HILOGE("Add Timer failed"); return false; } MMI_HILOGD("Add timer success"); isLaunchAbility = true; } return true; } bool KeyCommandHandler::IsKeyMatch(const ShortcutKey &shortcutKey, const std::shared_ptr &key) { CALL_DEBUG_ENTER; CHKPF(key); if ((key->GetKeyCode() != shortcutKey.finalKey) || (shortcutKey.triggerType != key->GetKeyAction())) { return false; } if ((shortcutKey.preKeys.size() + 1) != key->GetKeyItems().size()) { return false; } for (const auto &item : key->GetKeyItems()) { int32_t keyCode = item.GetKeyCode(); if (SkipFinalKey(keyCode, key)) { continue; } if (shortcutKey.preKeys.find(keyCode) == shortcutKey.preKeys.end()) { return false; } } MMI_HILOGD("Leave, key matched"); return true; } bool KeyCommandHandler::SkipFinalKey(const int32_t keyCode, const std::shared_ptr &key) { CHKPF(key); return keyCode == key->GetKeyCode(); } bool KeyCommandHandler::HandleKeyDown(ShortcutKey &shortcutKey) { CALL_DEBUG_ENTER; if (shortcutKey.keyDownDuration == 0) { MMI_HILOGD("Start launch ability immediately"); LaunchAbility(shortcutKey); return true; } shortcutKey.timerId = TimerMgr->AddTimer(shortcutKey.keyDownDuration, 1, [this, shortcutKey] () { MMI_HILOGD("Timer callback"); currentLaunchAbilityKey_ = shortcutKey; LaunchAbility(shortcutKey); }); if (shortcutKey.timerId < 0) { MMI_HILOGE("Add Timer failed"); return false; } MMI_HILOGD("Add timer success"); lastMatchedKey_ = shortcutKey; if (InputHandler->GetSubscriberHandler()->IsKeyEventSubscribed(shortcutKey.finalKey, shortcutKey.triggerType)) { MMI_HILOGD("current shortcutKey %{public}d is subSubcribed", shortcutKey.finalKey); return false; } return true; } int32_t KeyCommandHandler::GetKeyDownDurationFromXml(const std::string &businessId) { CALL_DEBUG_ENTER; std::shared_ptr pref = NativePreferences::PreferencesHelper::GetPreferences(shortKeyFileName, errno); CHKPR(pref, ERROR_DELAY_VALUE); return pref->GetInt(businessId, ERROR_DELAY_VALUE); } bool KeyCommandHandler::HandleKeyUp(const std::shared_ptr &keyEvent, const ShortcutKey &shortcutKey) { CALL_DEBUG_ENTER; CHKPF(keyEvent); if (shortcutKey.keyDownDuration == 0) { MMI_HILOGD("Start launch ability immediately"); LaunchAbility(shortcutKey); return true; } std::optional keyItem = keyEvent->GetKeyItem(); if (!keyItem) { MMI_HILOGE("The keyItem is nullopt"); return false; } auto upTime = keyEvent->GetActionTime(); auto downTime = keyItem->GetDownTime(); MMI_HILOGD("upTime:%{public}" PRId64 ",downTime:%{public}" PRId64 ",keyDownDuration:%{public}d", upTime, downTime, shortcutKey.keyDownDuration); if (upTime - downTime >= static_cast(shortcutKey.keyDownDuration) * 1000) { MMI_HILOGD("Skip, upTime - downTime >= duration"); return false; } MMI_HILOGD("Start launch ability immediately"); LaunchAbility(shortcutKey); return true; } bool KeyCommandHandler::HandleKeyCancel(ShortcutKey &shortcutKey) { CALL_DEBUG_ENTER; if (shortcutKey.timerId < 0) { MMI_HILOGE("Skip, timerid less than 0"); } auto timerId = shortcutKey.timerId; shortcutKey.timerId = -1; TimerMgr->RemoveTimer(timerId); MMI_HILOGD("timerId:%{public}d", timerId); return false; } void KeyCommandHandler::LaunchAbility(const Ability &ability, int64_t delay) { CALL_DEBUG_ENTER; AAFwk::Want want; want.SetElementName(ability.deviceId, ability.bundleName, ability.abilityName); want.SetAction(ability.action); want.SetUri(ability.uri); want.SetType(ability.uri); for (const auto &entity : ability.entities) { want.AddEntity(entity); } for (const auto &item : ability.params) { want.SetParam(item.first, item.second); } DfxHisysevent::CalcComboStartTimes(delay); DfxHisysevent::ReportComboStartTimes(); MMI_HILOGD("Start launch ability, bundleName:%{public}s", ability.bundleName.c_str()); ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want); if (err != ERR_OK) { MMI_HILOGE("LaunchAbility failed, bundleName:%{public}s, err:%{public}d", ability.bundleName.c_str(), err); } MMI_HILOGD("End launch ability, bundleName:%{public}s", ability.bundleName.c_str()); } void KeyCommandHandler::LaunchAbility(const ShortcutKey &key) { CALL_INFO_TRACE; LaunchAbility(key.ability, lastMatchedKey_.keyDownDuration); ResetLastMatchedKey(); } void KeyCommandHandler::LaunchAbility(const Sequence &sequence) { CALL_INFO_TRACE; LaunchAbility(sequence.ability, sequence.abilityStartDelay); } void ShortcutKey::Print() const { for (const auto &prekey: preKeys) { MMI_HILOGI("Eventkey matched, preKey:%{public}d", prekey); } MMI_HILOGD("Eventkey matched, finalKey:%{public}d, bundleName:%{public}s", finalKey, ability.bundleName.c_str()); } void KeyCommandHandler::RemoveSubscribedTimer(int32_t keyCode) { CALL_DEBUG_ENTER; auto iter = specialTimers_.find(keyCode); if (iter != specialTimers_.end()) { for (auto& item : iter->second) { TimerMgr->RemoveTimer(item); } specialTimers_.erase(keyCode); MMI_HILOGD("Remove timer success"); } } void KeyCommandHandler::HandleSpecialKeys(int32_t keyCode, int32_t keyAction) { CALL_DEBUG_ENTER; auto iter = specialKeys_.find(keyCode); if (keyAction == KeyEvent::KEY_ACTION_UP) { if (iter != specialKeys_.end()) { specialKeys_.erase(iter); return; } } if (keyAction == KeyEvent::KEY_ACTION_DOWN) { if (iter == specialKeys_.end()) { auto it = specialKeys_.emplace(keyCode, keyAction); if (!it.second) { MMI_HILOGD("KeyCode duplicated"); return; } } } } void KeyCommandHandler::InterruptTimers() { for (Sequence& item : filterSequences_) { if (item.timerId >= 0) { MMI_HILOGD("The key sequence change, close the timer"); TimerMgr->RemoveTimer(item.timerId); item.timerId = -1; } } } int32_t KeyCommandHandler::UpdateSettingsXml(const std::string &businessId, int32_t delay) { CALL_DEBUG_ENTER; if (businessId.empty() || businessIds_.empty()) { MMI_HILOGE("businessId or businessIds_ is empty"); return COMMON_PARAMETER_ERROR; } if (std::find(businessIds_.begin(), businessIds_.end(), businessId) == businessIds_.end()) { MMI_HILOGE("%{public}s not in the config file", businessId.c_str()); return COMMON_PARAMETER_ERROR; } if (delay < MIN_SHORT_KEY_DOWN_DURATION || delay > MAX_SHORT_KEY_DOWN_DURATION) { MMI_HILOGE("delay is not in valid range."); return COMMON_PARAMETER_ERROR; } std::shared_ptr pref = NativePreferences::PreferencesHelper::GetPreferences(shortKeyFileName, errno); CHKPR(pref, errno); pref->PutInt(businessId, delay); int32_t ret = pref->FlushSync(); if (ret != RET_OK) { MMI_HILOGE("Flush Sync failed, ret: %{public}d", ret); return ret; } return RET_OK; } KnuckleGesture KeyCommandHandler::GetSingleKnuckleGesture() { return singleKnuckleGesture_; } KnuckleGesture KeyCommandHandler::GetDoubleKnuckleGesture() { return doubleKnuckleGesture_; } } // namespace MMI } // namespace OHOS