diff --git a/common/src/itypes_util.cpp b/common/src/itypes_util.cpp index 3da31354d5de3d04324db053ebff85f4671bcad8..275a6f5a0c07494c7b2c20d5617944a283adde3d 100644 --- a/common/src/itypes_util.cpp +++ b/common/src/itypes_util.cpp @@ -188,7 +188,7 @@ bool ITypesUtil::Marshalling(const InputAttribute &input, MessageParcel &data) { if (!Marshal(data, input.inputPattern, input.enterKeyType, input.inputOption, input.isTextPreviewSupported, input.bundleName, input.immersiveMode, input.windowId, input.callingDisplayId, - input.placeholder, input.abilityName)) { + input.placeholder, input.abilityName, input.needAutoInputNumkey)) { IMSA_HILOGE("write InputAttribute to message parcel failed."); return false; } @@ -199,7 +199,7 @@ bool ITypesUtil::Unmarshalling(InputAttribute &output, MessageParcel &data) { if (!Unmarshal(data, output.inputPattern, output.enterKeyType, output.inputOption, output.isTextPreviewSupported, output.bundleName, output.immersiveMode, output.windowId, output.callingDisplayId, - output.placeholder, output.abilityName)) { + output.placeholder, output.abilityName, output.needAutoInputNumkey)) { IMSA_HILOGE("read InputAttribute from message parcel failed."); return false; } diff --git a/frameworks/js/napi/inputmethodability/js_keyboard_delegate_setting.cpp b/frameworks/js/napi/inputmethodability/js_keyboard_delegate_setting.cpp index 990f8a5ae4d005cdcece222820dedc199a5b36ab..03473c2a2948d23937c4e32a4047ef5593608a44 100644 --- a/frameworks/js/napi/inputmethodability/js_keyboard_delegate_setting.cpp +++ b/frameworks/js/napi/inputmethodability/js_keyboard_delegate_setting.cpp @@ -303,7 +303,7 @@ bool JsKeyboardDelegateSetting::OnDealKeyEvent(const std::shared_ptrGetKeyCode(), keyEvent->GetKeyAction(), false }; std::string type = (keyEvent->GetKeyAction() == ARGC_TWO ? "keyDown" : "keyUp"); auto keyCodeEntry = GetEntry(type, [¶](UvEntry &entry) { @@ -332,7 +332,7 @@ void JsKeyboardDelegateSetting::DealKeyEvent(const std::shared_ptr &key napi_value keyEventObject{}; auto result = napi_create_object(env, &keyEventObject); CHECK_RETURN((result == napi_ok) && (keyEventObject != nullptr), "create object", false); - result = MMI::KeyEventNapi::CreateKeyEvent(env, keyEventEntry->pullKeyEventPara, keyEventObject); + result = MMI::KeyEventNapi::CreateKeyEvent(env, keyEventEntry->fullKeyEventPara, keyEventObject); CHECK_RETURN((result == napi_ok) && (keyEventObject != nullptr), "create key event object", false); // 0 means the first param of callback. args[0] = keyEventObject; @@ -362,10 +362,12 @@ void JsKeyboardDelegateSetting::DealKeyEvent(const std::shared_ptr &key } bool consumeResult = isKeyEventConsumed || isKeyCodeConsumed; if (consumer != nullptr) { - consumer->OnKeyEventResult(consumeResult); if (!consumeResult) { IMSA_HILOGW("ime is not consumed, result: %{public}d.", consumeResult); + consumeResult = InputMethodAbility::GetInstance().HandleUnconsumedKey(keyEventEntry->fullKeyEventPara); } + IMSA_HILOGD("final consumed result: %{public}d.", consumeResult); + consumer->OnKeyEventResult(consumeResult); } } @@ -374,7 +376,7 @@ bool JsKeyboardDelegateSetting::OnKeyEvent(const std::shared_ptr { std::string type = "keyEvent"; auto entry = GetEntry(type, [keyEvent, &consumer](UvEntry &entry) { - entry.pullKeyEventPara = keyEvent; + entry.fullKeyEventPara = keyEvent; entry.keyEvenetConsumer = consumer; }); if (entry == nullptr) { @@ -397,7 +399,7 @@ bool JsKeyboardDelegateSetting::OnKeyEvent(const std::shared_ptr napi_value keyEventObject{}; auto result = napi_create_object(env, &keyEventObject); CHECK_RETURN((result == napi_ok) && (keyEventObject != nullptr), "create object", false); - result = MMI::KeyEventNapi::CreateKeyEvent(env, entry->pullKeyEventPara, keyEventObject); + result = MMI::KeyEventNapi::CreateKeyEvent(env, entry->fullKeyEventPara, keyEventObject); CHECK_RETURN((result == napi_ok) && (keyEventObject != nullptr), "create key event object", false); // 0 means the first param of callback. args[0] = keyEventObject; diff --git a/frameworks/js/napi/inputmethodability/js_keyboard_delegate_setting.h b/frameworks/js/napi/inputmethodability/js_keyboard_delegate_setting.h index a29db42838cd4938d28b3228f19ca7e97bc54302..95b808c59e77a0cb08f3097e0b4daa0e69671ebc 100644 --- a/frameworks/js/napi/inputmethodability/js_keyboard_delegate_setting.h +++ b/frameworks/js/napi/inputmethodability/js_keyboard_delegate_setting.h @@ -84,7 +84,7 @@ private: CursorPara curPara; SelectionPara selPara; KeyEventPara keyEventPara; - std::shared_ptr pullKeyEventPara; + std::shared_ptr fullKeyEventPara; std::string text; sptr keyEvenetConsumer = nullptr; InputAttribute inputAttribute; diff --git a/frameworks/native/inputmethod_ability/include/input_method_ability.h b/frameworks/native/inputmethod_ability/include/input_method_ability.h index dd3841220805c656a0daf0f53ac4be6c5bf524e0..6c24bf2ddf2d357cfdde0d363a1136c84ef2ca0f 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_ability.h +++ b/frameworks/native/inputmethod_ability/include/input_method_ability.h @@ -107,6 +107,7 @@ public: int32_t RegisterMsgHandler(const std::shared_ptr &msgHandler = nullptr); int32_t OnCallingDisplayIdChanged(uint64_t displayId); int32_t OnSendPrivateData(const std::unordered_map &privateCommand); + bool HandleUnconsumedKey(const std::shared_ptr &keyEvent); public: /* called from TaskManager worker thread */ diff --git a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp index a505ae8c7304436eda828d6a50421780c4ee7405..0294260f61100f66b644cff1584128164c8a63d8 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp @@ -1757,5 +1757,47 @@ int32_t InputMethodAbility::OnSendPrivateData(const std::unordered_map &keyEvent) +{ + if (keyEvent == nullptr) { + IMSA_HILOGE("keyEvent nullptr"); + return false; + } + auto channel = GetInputDataChannelProxy(); + if (channel == nullptr) { + IMSA_HILOGD("channel is nullptr!"); + return false; + } + if (!GetInputAttribute().needAutoInputNumkey) { + IMSA_HILOGD("no need"); + return false; + } + if (keyEvent->GetKeyAction() != MMI::KeyEvent::KEY_ACTION_DOWN) { + IMSA_HILOGD("not down key"); + return false; + } + if (keyEvent->GetPressedKeys().size() > 1) { + IMSA_HILOGD("only handle single key"); + return false; + } + int32_t keyCode = keyEvent->GetKeyCode(); + std::string inputNumber; + if (MMI::KeyEvent::KEYCODE_0 <= keyCode && keyCode <= MMI::KeyEvent::KEYCODE_9) { + IMSA_HILOGD("auto input a number"); + channel->InsertTextAsync(std::to_string(keyCode - MMI::KeyEvent::KEYCODE_0)); + return true; + } + if (!keyEvent->GetFunctionKey(MMI::KeyEvent::NUM_LOCK_FUNCTION_KEY)) { + IMSA_HILOGD("num lock off"); + return false; + } + if (MMI::KeyEvent::KEYCODE_NUMPAD_0 <= keyCode && keyCode <= MMI::KeyEvent::KEYCODE_NUMPAD_9) { + IMSA_HILOGD("auto input a number"); + channel->InsertTextAsync(std::to_string(keyCode - MMI::KeyEvent::KEYCODE_NUMPAD_0)); + return true; + } + return false; +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/inputmethod_controller/IInputDataChannel.idl b/frameworks/native/inputmethod_controller/IInputDataChannel.idl index b798d6359099ab7443dd6f9590538dc50b7b00ea..d810d6f3650897c87be27514124715f2619afa97 100644 --- a/frameworks/native/inputmethod_controller/IInputDataChannel.idl +++ b/frameworks/native/inputmethod_controller/IInputDataChannel.idl @@ -22,6 +22,7 @@ sequenceable input_method_utils..OHOS.MiscServices.RangeInner; sequenceable input_method_utils..OHOS.MiscServices.ArrayBuffer; interface OHOS.MiscServices.IInputDataChannel { [ipccode 0] void InsertText([in] String text); + [oneway] void InsertTextAsync([in] String text); void DeleteForward([in] int length); void DeleteBackward([in] int length); void GetTextBeforeCursor([in] int number, [out] String text); diff --git a/frameworks/native/inputmethod_controller/include/input_attribute.h b/frameworks/native/inputmethod_controller/include/input_attribute.h index bd12fb748817723e270e7137a291762e69de06de..1bab83feeb35b43dffcd21a332af358cf47705bf 100644 --- a/frameworks/native/inputmethod_controller/include/input_attribute.h +++ b/frameworks/native/inputmethod_controller/include/input_attribute.h @@ -41,6 +41,7 @@ struct InputAttribute { uint64_t callingDisplayId = 0; std::u16string placeholder { u"" }; std::u16string abilityName { u"" }; + bool needAutoInputNumkey { false }; // number keys need to be automatically handled by imf bool GetSecurityFlag() const { @@ -72,6 +73,7 @@ struct InputAttribute { << "isTextPreviewSupported:" << isTextPreviewSupported << "bundleName:" << bundleName << "immersiveMode:" << immersiveMode << "windowId:" << windowId << "callingDisplayId:" << callingDisplayId + << "needNumInput: " << needAutoInputNumkey << "]"; return ss.str(); } @@ -93,6 +95,7 @@ struct InputAttributeInner : public Parcelable { uint64_t callingDisplayId = 0; std::u16string placeholder { u"" }; std::u16string abilityName { u"" }; + bool needAutoInputNumkey { false }; // number keys need to be automatically handled by imf bool ReadFromParcel(Parcel &in) { @@ -106,6 +109,7 @@ struct InputAttributeInner : public Parcelable { callingDisplayId = in.ReadUint64(); placeholder = in.ReadString16(); abilityName = in.ReadString16(); + needAutoInputNumkey = in.ReadBool(); return true; } @@ -136,6 +140,7 @@ struct InputAttributeInner : public Parcelable { return false; } auto ret = out.WriteString16(placeholder) && out.WriteString16(abilityName); + ret = ret && out.WriteBool(needAutoInputNumkey); return ret; } diff --git a/frameworks/native/inputmethod_controller/include/input_data_channel_service_impl.h b/frameworks/native/inputmethod_controller/include/input_data_channel_service_impl.h index 33598686fefc5293731c0855edac4773ecb892ef..fb21f384ddba94892ac54f27018eeaa461ffab39 100644 --- a/frameworks/native/inputmethod_controller/include/input_data_channel_service_impl.h +++ b/frameworks/native/inputmethod_controller/include/input_data_channel_service_impl.h @@ -32,6 +32,7 @@ public: ~InputDataChannelServiceImpl(); ErrCode InsertText(const std::string &text) override; + ErrCode InsertTextAsync(const std::string &text) override; ErrCode DeleteForward(int32_t length) override; ErrCode DeleteBackward(int32_t length) override; ErrCode GetTextBeforeCursor(int32_t number, std::string &text) override; diff --git a/frameworks/native/inputmethod_controller/src/input_data_channel_service_impl.cpp b/frameworks/native/inputmethod_controller/src/input_data_channel_service_impl.cpp index 3f4830b1b14cd42f4640b218ce82861b892b7424..a5744e753329f1b804b7dcbd440960d841f8d350 100644 --- a/frameworks/native/inputmethod_controller/src/input_data_channel_service_impl.cpp +++ b/frameworks/native/inputmethod_controller/src/input_data_channel_service_impl.cpp @@ -39,6 +39,16 @@ ErrCode InputDataChannelServiceImpl::InsertText(const std::string &text) return instance->InsertText(Str8ToStr16(text)); } +ErrCode InputDataChannelServiceImpl::InsertTextAsync(const std::string &text) +{ + auto instance = InputMethodController::GetInstance(); + if (instance == nullptr) { + IMSA_HILOGE("failed to get InputMethodController instance!"); + return ErrorCode::ERROR_EX_NULL_POINTER; + } + return instance->InsertText(Str8ToStr16(text)); +} + ErrCode InputDataChannelServiceImpl::DeleteForward(int32_t length) { auto instance = InputMethodController::GetInstance(); diff --git a/frameworks/native/inputmethod_controller/src/input_method_tools.cpp b/frameworks/native/inputmethod_controller/src/input_method_tools.cpp index 43cf625fbd1eec1bf99466246469255be501f9c6..e2fdf3a07ecb4c22621c6b566cfd4befed25e385 100644 --- a/frameworks/native/inputmethod_controller/src/input_method_tools.cpp +++ b/frameworks/native/inputmethod_controller/src/input_method_tools.cpp @@ -37,6 +37,7 @@ InputAttributeInner InputMethodTools::AttributeToInner(const InputAttribute &att inner.callingDisplayId = attribute.callingDisplayId; inner.placeholder = attribute.placeholder; inner.abilityName = attribute.abilityName; + inner.needAutoInputNumkey = attribute.needAutoInputNumkey; return inner; } @@ -53,6 +54,7 @@ InputAttribute InputMethodTools::InnerToAttribute(const InputAttributeInner &inn inputAttribute.callingDisplayId = inner.callingDisplayId; inputAttribute.placeholder = inner.placeholder; inputAttribute.abilityName = inner.abilityName; + inputAttribute.needAutoInputNumkey = inner.needAutoInputNumkey; return inputAttribute; } diff --git a/services/adapter/settings_data_provider/BUILD.gn b/services/adapter/settings_data_provider/BUILD.gn index 080faa29d356533cc1add1015240fd0d61be61b1..2457812151cc2c5acab687b5c93ee045906c3150 100644 --- a/services/adapter/settings_data_provider/BUILD.gn +++ b/services/adapter/settings_data_provider/BUILD.gn @@ -39,6 +39,7 @@ ohos_static_library("settings_data_static") { "common/src/settings_data_utils.cpp", "src/ime_enabled_info_manager.cpp", "src/enable_upgrade_manager.cpp", + "src/numkey_apps_manager.cpp", ] public_configs = [ ":settings_data_config" ] diff --git a/services/adapter/settings_data_provider/common/include/settings_data_observer.h b/services/adapter/settings_data_provider/common/include/settings_data_observer.h index f51ea06bb50f6d541b210f91ba93df8132002e7c..1b839f1c0cc224634514687013dc76273a6da474 100644 --- a/services/adapter/settings_data_provider/common/include/settings_data_observer.h +++ b/services/adapter/settings_data_provider/common/include/settings_data_observer.h @@ -25,12 +25,15 @@ namespace MiscServices { class SettingsDataObserver : public AAFwk::DataAbilityObserverStub { public: using CallbackFunc = std::function; - SettingsDataObserver(const std::string &key, CallbackFunc &func) : key_(key), func_(func){}; + SettingsDataObserver(const std::string &uriProxy, const std::string &key, const CallbackFunc &func) + : uriProxy_(uriProxy), key_(key), func_(func){}; ~SettingsDataObserver() = default; void OnChange() override; + const std::string &GetUriProxy(); const std::string &GetKey(); private: + std::string uriProxy_; std::string key_; CallbackFunc func_ = nullptr; }; diff --git a/services/adapter/settings_data_provider/common/include/settings_data_utils.h b/services/adapter/settings_data_provider/common/include/settings_data_utils.h index 9d66b56e98cd571ea41ffdc1200ea65b8d71ed6f..a76c132bea8e95a70aa760a0d3aaef5c6fe145d2 100644 --- a/services/adapter/settings_data_provider/common/include/settings_data_utils.h +++ b/services/adapter/settings_data_provider/common/include/settings_data_utils.h @@ -16,6 +16,8 @@ #ifndef SETTINGS_DATA_UTILS_H #define SETTINGS_DATA_UTILS_H +#include + #include "datashare_helper.h" #include "input_method_property.h" #include "serializable.h" @@ -37,7 +39,10 @@ public: static SettingsDataUtils &GetInstance(); std::shared_ptr CreateDataShareHelper(const std::string &uriProxy); int32_t CreateAndRegisterObserver( - const std::string &uriProxy, const std::string &key, SettingsDataObserver::CallbackFunc func); + const std::string &uriProxy, const std::string &key, const SettingsDataObserver::CallbackFunc &func); + int32_t RegisterObserver(const std::string &uriProxy, const std::string &key, + const SettingsDataObserver::CallbackFunc &func, sptr &observer); + int32_t UnregisterObserver(const sptr &observer); int32_t GetStringValue(const std::string &uriProxy, const std::string &key, std::string &value); bool SetStringValue(const std::string &uriProxy, const std::string &key, const std::string &value); bool ReleaseDataShareHelper(std::shared_ptr &helper); @@ -48,15 +53,14 @@ public: private: SettingsDataUtils() = default; ~SettingsDataUtils(); - int32_t RegisterObserver(const std::string &uriProxy, const sptr &observer); - int32_t UnregisterObserver(const std::string &uriProxy, const sptr &observer); + int32_t RegisterObserver(const sptr &observer); sptr GetToken(); private: std::mutex remoteObjMutex_; sptr remoteObj_ = nullptr; std::mutex observerListMutex_; - std::vector>> observerList_; + std::list> observerList_; std::atomic isDataShareReady_{ false }; }; } // namespace MiscServices diff --git a/services/adapter/settings_data_provider/common/src/settings_data_observer.cpp b/services/adapter/settings_data_provider/common/src/settings_data_observer.cpp index 94395818a4c818800a800a26e5fb608b4e12c3e4..c43c00f7505882e1ed2a76f03b44cc4693ed3fae 100644 --- a/services/adapter/settings_data_provider/common/src/settings_data_observer.cpp +++ b/services/adapter/settings_data_provider/common/src/settings_data_observer.cpp @@ -24,6 +24,11 @@ void SettingsDataObserver::OnChange() } } +const std::string &SettingsDataObserver::GetUriProxy() +{ + return uriProxy_; +} + const std::string &SettingsDataObserver::GetKey() { return key_; diff --git a/services/adapter/settings_data_provider/common/src/settings_data_utils.cpp b/services/adapter/settings_data_provider/common/src/settings_data_utils.cpp index e3f6d4a0c2921f8dbc5fac35c6be658ba602a839..5940363c42d10e52a6e18ebe9b21a48bee4fe798 100644 --- a/services/adapter/settings_data_provider/common/src/settings_data_utils.cpp +++ b/services/adapter/settings_data_provider/common/src/settings_data_utils.cpp @@ -29,7 +29,7 @@ SettingsDataUtils::~SettingsDataUtils() std::lock_guard lock(observerListMutex_); if (!observerList_.empty()) { for (auto &iter : observerList_) { - UnregisterObserver(iter.first, iter.second); + UnregisterObserver(iter); } observerList_.clear(); } @@ -42,25 +42,36 @@ SettingsDataUtils &SettingsDataUtils::GetInstance() } int32_t SettingsDataUtils::CreateAndRegisterObserver( - const std::string &uriProxy, const std::string &key, SettingsDataObserver::CallbackFunc func) + const std::string &uriProxy, const std::string &key, const SettingsDataObserver::CallbackFunc &func) { IMSA_HILOGD("uriProxy:%{public}s, key: %{public}s.", uriProxy.c_str(), key.c_str()); - sptr observer = new (std::nothrow) SettingsDataObserver(key, func); + sptr observer = new (std::nothrow) SettingsDataObserver(uriProxy, key, func); if (observer == nullptr) { IMSA_HILOGE("observer is nullptr!"); return ErrorCode::ERROR_NULL_POINTER; } - return RegisterObserver(uriProxy, observer); + return RegisterObserver(observer); } -int32_t SettingsDataUtils::RegisterObserver(const std::string &uriProxy, const sptr &observer) +int32_t SettingsDataUtils::RegisterObserver(const std::string &uriProxy, const std::string &key, + const SettingsDataObserver::CallbackFunc &func, sptr &observer) { + observer = new (std::nothrow) SettingsDataObserver(uriProxy, key, func); if (observer == nullptr) { IMSA_HILOGE("observer is nullptr!"); return ErrorCode::ERROR_NULL_POINTER; } - auto uri = GenerateTargetUri(uriProxy, observer->GetKey()); - auto helper = SettingsDataUtils::CreateDataShareHelper(uriProxy); + return RegisterObserver(observer); +} + +int32_t SettingsDataUtils::RegisterObserver(const sptr &observer) +{ + if (observer == nullptr) { + IMSA_HILOGE("observer is nullptr!"); + return ErrorCode::ERROR_NULL_POINTER; + } + auto uri = GenerateTargetUri(observer->GetUriProxy(), observer->GetKey()); + auto helper = SettingsDataUtils::CreateDataShareHelper(observer->GetUriProxy()); if (helper == nullptr) { IMSA_HILOGE("helper is nullptr!"); return ErrorCode::ERROR_NULL_POINTER; @@ -70,24 +81,28 @@ int32_t SettingsDataUtils::RegisterObserver(const std::string &uriProxy, const s IMSA_HILOGD("succeed to register observer of uri: %{public}s.", uri.ToString().c_str()); std::lock_guard lock(observerListMutex_); - observerList_.push_back(std::make_pair(uriProxy, observer)); + observerList_.push_back(observer); return ErrorCode::NO_ERROR; } -int32_t SettingsDataUtils::UnregisterObserver(const std::string &uriProxy, const sptr &observer) +int32_t SettingsDataUtils::UnregisterObserver(const sptr &observer) { if (observer == nullptr) { IMSA_HILOGE("observer is nullptr!"); return ErrorCode::ERROR_NULL_POINTER; } - auto uri = GenerateTargetUri(uriProxy, observer->GetKey()); - auto helper = SettingsDataUtils::CreateDataShareHelper(uriProxy); + auto uri = GenerateTargetUri(observer->GetUriProxy(), observer->GetKey()); + auto helper = SettingsDataUtils::CreateDataShareHelper(observer->GetUriProxy()); if (helper == nullptr) { - return ErrorCode::ERROR_ENABLE_IME; + IMSA_HILOGE("helper is nullptr!"); + return ErrorCode::ERROR_NULL_POINTER; } helper->UnregisterObserver(uri, observer); ReleaseDataShareHelper(helper); IMSA_HILOGD("succeed to unregister observer of uri: %{public}s.", uri.ToString().c_str()); + + std::lock_guard lock(observerListMutex_); + observerList_.remove(observer); return ErrorCode::NO_ERROR; } diff --git a/services/adapter/settings_data_provider/include/numkey_apps_manager.h b/services/adapter/settings_data_provider/include/numkey_apps_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..08e4cc68bb71e5202a0c7796d77d43fa22a7bb14 --- /dev/null +++ b/services/adapter/settings_data_provider/include/numkey_apps_manager.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2025 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. + */ + +#ifndef INPUTMETHOD_IMF_AUTO_NUMBER_INPUT_APPS_MANAGER_H +#define INPUTMETHOD_IMF_AUTO_NUMBER_INPUT_APPS_MANAGER_H + +#include "settings_data_utils.h" + +namespace OHOS { +namespace MiscServices { +static constexpr int32_t BLOCK_MODE = 8; +struct NumkeyAPP : public Serializable { + std::string name; + bool numKey{ false }; + bool Unmarshal(cJSON *node) override + { + GetValue(node, GET_NAME(name), name); + GetValue(node, GET_NAME(numKey), numKey); + return true; + } +}; + +struct NumkeyAppListCfg : public Serializable { + std::vector numkeyApps; + bool Unmarshal(cJSON *node) override + { + std::function filter = [](const NumkeyAPP &app) { return app.numKey; }; + GetValues(node, numkeyApps, filter); + return true; + } +}; + +struct UserBlockListCfg : public Serializable { + std::vector blockApps; + bool Unmarshal(cJSON *node) override + { + std::function filter = [](const int32_t &mode) { return mode == BLOCK_MODE; }; + GetKeys(node, blockApps, filter); + return true; + } +}; + +class NumkeyAppsManager { +public: + static NumkeyAppsManager &GetInstance(); + int32_t Init(int32_t userId); + bool NeedAutoNumKeyInput(int32_t userId, const std::string &bundleName); + int32_t OnUserSwitched(int32_t userId); + int32_t OnUserRemoved(int32_t userId); + int32_t RegisterUserBlockListData(int32_t userId); + static constexpr const char *COMPATIBLE_SETTING_STRATEGY = "COMPATIBLE_SETTING_STRATEGY"; + static constexpr const char *COMPATIBLE_APP_STRATEGY = "COMPATIBLE_APP_STRATEGY"; + +private: + NumkeyAppsManager() = default; + ~NumkeyAppsManager(); + NumkeyAppsManager(const NumkeyAppsManager &) = delete; + NumkeyAppsManager(NumkeyAppsManager &&) = delete; + NumkeyAppsManager &operator=(const NumkeyAppsManager &) = delete; + NumkeyAppsManager &operator=(NumkeyAppsManager &&) = delete; + + int32_t InitWhiteList(); + int32_t UpdateUserBlockList(int32_t userId); + static int32_t ParseWhiteList(std::unordered_set &list); + static int32_t ParseBlockList(int32_t userId, std::unordered_set &list); + + bool isFeatureEnabled_{ false }; + + std::atomic isListInited_{ false }; + std::mutex appListLock_; + std::unordered_set numKeyAppList_; + + std::mutex blockListLock_; + std::map> usersBlockList_; + std::mutex observersLock_; + std::map> observers_; +}; +} // namespace MiscServices +} // namespace OHOS + +#endif // INPUTMETHOD_IMF_AUTO_NUMBER_INPUT_APPS_MANAGER_H diff --git a/services/adapter/settings_data_provider/src/numkey_apps_manager.cpp b/services/adapter/settings_data_provider/src/numkey_apps_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d084ec231da3e8908a425d903da2913582a0224 --- /dev/null +++ b/services/adapter/settings_data_provider/src/numkey_apps_manager.cpp @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2025 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 "numkey_apps_manager.h" + +#include "global.h" +#include "ime_info_inquirer.h" + +namespace OHOS { +namespace MiscServices { +#define CHECK_FEATURE_DISABLED_RETURN(retVal) \ + do { \ + if (!isFeatureEnabled_) { \ + IMSA_HILOGD("feature not enabled"); \ + return retVal; \ + } \ + } while (0) + +NumkeyAppsManager &NumkeyAppsManager::GetInstance() +{ + static NumkeyAppsManager numkeyAppsManager; + return numkeyAppsManager; +} + +NumkeyAppsManager::~NumkeyAppsManager() +{ + if (observers_.empty()) { + return; + } + std::map> observers; + { + std::lock_guard lock(observersLock_); + observers = observers_; + observers_.clear(); + } + for (auto &observer : observers) { + SettingsDataUtils::GetInstance().UnregisterObserver(observer.second); + } +} + +int32_t NumkeyAppsManager::Init(int32_t userId) +{ + IMSA_HILOGI("start, userId: %{public}d", userId); + isFeatureEnabled_ = ImeInfoInquirer::GetInstance().IsEnableNumKey(); + CHECK_FEATURE_DISABLED_RETURN(ErrorCode::NO_ERROR); + + int32_t ret = InitWhiteList(); + IMSA_HILOGI("InitWhiteList ret: %{public}d", ret); + + ret = RegisterUserBlockListData(userId); + IMSA_HILOGI("RegisterUserBlockListData ret: %{public}d", ret); + + ret = UpdateUserBlockList(userId); + IMSA_HILOGI("UpdateUserBlockList ret: %{public}d", ret); + return ret; +} + +bool NumkeyAppsManager::NeedAutoNumKeyInput(int32_t userId, const std::string &bundleName) +{ + CHECK_FEATURE_DISABLED_RETURN(false); + { + std::lock_guard lock(appListLock_); + if (numKeyAppList_.find(bundleName) == numKeyAppList_.end()) { + IMSA_HILOGD("not in white list %{public}s", bundleName.c_str()); + return false; + } + } + std::lock_guard lock(blockListLock_); + auto iter = usersBlockList_.find(userId); + if (iter == usersBlockList_.end()) { + IMSA_HILOGD("user %{public}d block list is empty", userId); + return true; + } + auto blockList = iter->second; + bool needAutoInput = blockList.find(bundleName) == blockList.end(); + IMSA_HILOGD("bundleName: %{public}s, needAutoInput: %{public}d", bundleName.c_str(), needAutoInput); + return needAutoInput; +} + +int32_t NumkeyAppsManager::OnUserSwitched(int32_t userId) +{ + CHECK_FEATURE_DISABLED_RETURN(ErrorCode::NO_ERROR); + IMSA_HILOGI("userId %{public}d", userId); + { + std::lock_guard lock(blockListLock_); + if (usersBlockList_.find(userId) != usersBlockList_.end()) { + IMSA_HILOGI("block list already set"); + return ErrorCode::NO_ERROR; + } + } + RegisterUserBlockListData(userId); + int32_t ret = UpdateUserBlockList(userId); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("UpdateUserBlockList failed, ret: %{public}d", ret); + return ret; + } + return ErrorCode::NO_ERROR; +} + +int32_t NumkeyAppsManager::OnUserRemoved(int32_t userId) +{ + CHECK_FEATURE_DISABLED_RETURN(ErrorCode::NO_ERROR); + IMSA_HILOGI("userId %{public}d", userId); + sptr observer = nullptr; + { + std::lock_guard lock(observersLock_); + auto iter = observers_.find(userId); + if (iter == observers_.end()) { + IMSA_HILOGD("observer not found"); + return ErrorCode::NO_ERROR; + } + observer = iter->second; + } + int32_t ret = SettingsDataUtils::GetInstance().UnregisterObserver(observer); + { + std::lock_guard lock(observersLock_); + observers_.erase(userId); + } + return ret; +} + +int32_t NumkeyAppsManager::InitWhiteList() +{ + if (isListInited_.load()) { + return ErrorCode::NO_ERROR; + } + std::unordered_set whiteList; + int32_t ret = ParseWhiteList(whiteList); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGI("ParseWhiteList failed, ret: %{public}d", ret); + return ret; + } + std::lock_guard lock(appListLock_); + numKeyAppList_ = whiteList; + IMSA_HILOGI("success, list size: %{public}zu", numKeyAppList_.size()); + return ErrorCode::NO_ERROR; +} + +int32_t NumkeyAppsManager::UpdateUserBlockList(int32_t userId) +{ + std::unordered_set blockList; + int32_t ret = ParseBlockList(userId, blockList); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("ParseBlockList failed, ret: %{public}d", ret); + return ret; + } + std::lock_guard lock(blockListLock_); + usersBlockList_[userId] = blockList; + IMSA_HILOGI("success, list size: %{public}zu", blockList.size()); + return ErrorCode::NO_ERROR; +} + +int32_t NumkeyAppsManager::ParseWhiteList(std::unordered_set &list) +{ + std::string valueStr; + int32_t ret = SettingsDataUtils::GetInstance().GetStringValue(SETTING_URI_PROXY, COMPATIBLE_APP_STRATEGY, valueStr); + if (ret != ErrorCode::NO_ERROR && ret != ErrorCode::ERROR_KEYWORD_NOT_FOUND) { + IMSA_HILOGE("failed to get white list from settings data, ret: %{public}d", ret); + return ret; + } + if (ret == ErrorCode::ERROR_KEYWORD_NOT_FOUND) { + IMSA_HILOGD("key not found"); + return ErrorCode::NO_ERROR; + } + NumkeyAppListCfg whiteListCfg; + if (!whiteListCfg.Unmarshall(valueStr)) { + IMSA_HILOGE("unmarshall failed"); + return ErrorCode::ERROR_PARSE_CONFIG_FILE; + } + for (const auto &app : whiteListCfg.numkeyApps) { + list.insert(app.name); + } + return ErrorCode::NO_ERROR; +} + +int32_t NumkeyAppsManager::ParseBlockList(int32_t userId, std::unordered_set &list) +{ + std::string valueStr; + int32_t ret = SettingsDataUtils::GetInstance().GetStringValue( + SETTINGS_USER_DATA_URI + std::to_string(userId) + "?Proxy=true", COMPATIBLE_SETTING_STRATEGY, valueStr); + if (ret != ErrorCode::NO_ERROR && ret != ErrorCode::ERROR_KEYWORD_NOT_FOUND) { + IMSA_HILOGE("failed to get white list from settings data, ret: %{public}d", ret); + return ret; + } + if (ret == ErrorCode::ERROR_KEYWORD_NOT_FOUND) { + IMSA_HILOGD("key not found"); + return ErrorCode::NO_ERROR; + } + UserBlockListCfg blockListCfg; + if (!blockListCfg.Unmarshall(valueStr)) { + IMSA_HILOGE("unmarshall failed"); + return ErrorCode::ERROR_PARSE_CONFIG_FILE; + } + for (const auto &app : blockListCfg.blockApps) { + list.insert(app); + } + return ErrorCode::NO_ERROR; +} + +int32_t NumkeyAppsManager::RegisterUserBlockListData(int32_t userId) +{ + auto func = [this, userId]() { + IMSA_HILOGI("on block list change, userId: %{public}d", userId); + UpdateUserBlockList(userId); + }; + std::string uriProxy = SETTINGS_USER_DATA_URI + std::to_string(userId) + "?Proxy=true"; + sptr observer = nullptr; + int32_t ret = + SettingsDataUtils::GetInstance().RegisterObserver(uriProxy, COMPATIBLE_SETTING_STRATEGY, func, observer); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("RegisterObserver failed, ret: %{public}d", ret); + return ret; + } + IMSA_HILOGI("end, userId: %{public}d ", userId); + std::lock_guard lock(observersLock_); + observers_[userId] = observer; + return ErrorCode::NO_ERROR; +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/services/include/ime_info_inquirer.h b/services/include/ime_info_inquirer.h index 72440ff90053967be736c5bdf405a72a88deeb42..c8d42c713e8279d345fda6bfbeb26360ec986f99 100644 --- a/services/include/ime_info_inquirer.h +++ b/services/include/ime_info_inquirer.h @@ -88,6 +88,7 @@ public: bool IsEnableInputMethod(); bool IsEnableSecurityMode(); bool IsEnableAppAgent(); + bool IsEnableNumKey(); bool IsVirtualProxyIme(int32_t callingUid); bool IsSpecialSaUid(int32_t callingUid); void InitSystemConfig(); diff --git a/services/include/peruser_session.h b/services/include/peruser_session.h index de2952484350f5ca7a8da96a2f16e8cab5377940..e7e52d7271115eb562759698af5012f52710d446 100644 --- a/services/include/peruser_session.h +++ b/services/include/peruser_session.h @@ -148,6 +148,7 @@ public: int32_t SpecialSendPrivateData(const std::unordered_map &privateCommand); uint64_t GetDisplayGroupId(uint64_t displayId); bool IsDefaultDisplayGroup(uint64_t displayId); + bool IsNumkeyAutoInputApp(const std::string &bundleName); private: struct ResetManager { diff --git a/services/include/sys_cfg_parser.h b/services/include/sys_cfg_parser.h index 73d12528e0ee6c61e0f24e7842f98376feacb1da..68012f8058e05f5c11820e1f9ebee501bfa83d50 100644 --- a/services/include/sys_cfg_parser.h +++ b/services/include/sys_cfg_parser.h @@ -28,6 +28,7 @@ struct SystemConfig : public Serializable { bool enableFullExperienceFeature = false; EnabledStatus initEnabledState{ EnabledStatus::DISABLED }; bool enableAppAgentFeature = false; + bool enableNumKeyFeature = false; std::unordered_set proxyImeUidList; std::unordered_set specialSaUidList; std::unordered_set defaultImeScreenList; @@ -41,6 +42,7 @@ struct SystemConfig : public Serializable { GetValue(node, GET_NAME(initEnabledState), enableState); initEnabledState = static_cast(enableState); GetValue(node, GET_NAME(enableAppAgentFeature), enableAppAgentFeature); + GetValue(node, GET_NAME(enableNumKeyFeature), enableNumKeyFeature); GetValue(node, GET_NAME(proxyImeUidList), proxyImeUidList); GetValue(node, GET_NAME(specialSaUidList), specialSaUidList); GetValue(node, GET_NAME(defaultImeScreenList), defaultImeScreenList); diff --git a/services/json/include/serializable.h b/services/json/include/serializable.h index ea85f7d4c2caeb746bf7dd4f17bd3141d1dda805..66ed8163f5767e838271fc4441d7202dff3797e0 100644 --- a/services/json/include/serializable.h +++ b/services/json/include/serializable.h @@ -45,6 +45,48 @@ public: static bool GetValue(cJSON *node, const std::string &name, Serializable &value); static bool GetValue(cJSON *node, const std::string &name, std::vector> &values); template + static bool GetKeys(cJSON *nodes, std::vector &keys, const std::function &filter = nullptr) + { + if (nodes == nullptr) { + IMSA_HILOGE("nodes nullptr"); + return false; + } + cJSON *child = nodes->child; + bool result = true; + while (child != nullptr) { + std::string nodeKey = child->string; + T value; + bool ret = GetValue(child, "", value); + if (ret && (filter == nullptr || filter(value))) { + keys.push_back(nodeKey); + } + result = result && ret; + child = child->next; + } + return result; + } + template + static bool GetValues(cJSON *nodes, std::vector &values, const std::function &filter = nullptr) + { + if (nodes == nullptr) { + IMSA_HILOGE("nodes nullptr"); + return false; + } + cJSON *child = nodes->child; + bool result = true; + while (child != nullptr) { + std::string nodeKey = child->string; + T value; + bool ret = GetValue(child, "", value); + if (ret && (filter == nullptr || filter(value))) { + values.push_back(value); + } + result = result && ret; + child = child->next; + } + return result; + } + template static bool GetValue(cJSON *node, const std::string &name, std::vector &values, int32_t maxNum = 0) { auto subNode = GetSubNode(node, name); diff --git a/services/src/ime_info_inquirer.cpp b/services/src/ime_info_inquirer.cpp index 18ff5a8bfd331a64e8f105196993c00f08d87ad4..8d33c00f1fddffb2eaadb45b74de1dbec7ef6858 100644 --- a/services/src/ime_info_inquirer.cpp +++ b/services/src/ime_info_inquirer.cpp @@ -60,6 +60,11 @@ bool ImeInfoInquirer::IsEnableAppAgent() return systemConfig_.enableAppAgentFeature; } +bool ImeInfoInquirer::IsEnableNumKey() +{ + return systemConfig_.enableNumKeyFeature; +} + bool ImeInfoInquirer::IsVirtualProxyIme(int32_t callingUid) { return systemConfig_.proxyImeUidList.find(callingUid) != systemConfig_.proxyImeUidList.end(); diff --git a/services/src/input_method_system_ability.cpp b/services/src/input_method_system_ability.cpp index 5d502e2852a0b9ae961742af9ac71f60b5daf3f8..5e366846db0832ad0e8b938b0c499bf3d179539c 100644 --- a/services/src/input_method_system_ability.cpp +++ b/services/src/input_method_system_ability.cpp @@ -31,6 +31,7 @@ #include "iservice_registry.h" #include "itypes_util.h" #include "mem_mgr_client.h" +#include "numkey_apps_manager.h" #include "inputmethod_message_handler.h" #include "os_account_adapter.h" #include "scene_board_judgement.h" @@ -377,6 +378,7 @@ void InputMethodSystemAbility::UpdateUserInfo(int32_t userId) userId_ = userId; UserSessionManager::GetInstance().AddUserSession(userId_); InputMethodSysEvent::GetInstance().SetUserId(userId_); + NumkeyAppsManager::GetInstance().OnUserSwitched(userId_); } int32_t InputMethodSystemAbility::OnIdle(const SystemAbilityOnDemandReason &idleReason) @@ -567,6 +569,8 @@ int32_t InputMethodSystemAbility::GenerateClientInfo(int32_t userId, InputClient clientInfo.config.windowId = callingWindowInfo.windowId; clientInfo.config.inputAttribute.windowId = callingWindowInfo.windowId; clientInfo.config.inputAttribute.callingDisplayId = callingWindowInfo.displayId; + clientInfo.config.inputAttribute.needAutoInputNumkey = + session->IsNumkeyAutoInputApp(clientInfo.config.inputAttribute.bundleName); IMSA_HILOGD("result:%{public}s,wid:%{public}d", clientInfo.config.inputAttribute.ToString().c_str(), clientInfo.config.windowId); } @@ -1550,6 +1554,7 @@ int32_t InputMethodSystemAbility::OnUserRemoved(const Message *msg) UserSessionManager::GetInstance().RemoveUserSession(userId); } FullImeInfoManager::GetInstance().Delete(userId); + NumkeyAppsManager::GetInstance().OnUserRemoved(userId); return ErrorCode::NO_ERROR; } @@ -1813,6 +1818,7 @@ void InputMethodSystemAbility::HandleDataShareReady() } SettingsDataUtils::GetInstance().NotifyDataShareReady(); FullImeInfoManager::GetInstance().Init(); + NumkeyAppsManager::GetInstance().Init(userId_); } int32_t InputMethodSystemAbility::InitAccountMonitor() diff --git a/services/src/peruser_session.cpp b/services/src/peruser_session.cpp index 6ce22ce11d624619b2f4911bbdd9a56068f23823..96d16bd72169069a43f04e5498d4d788c69b018a 100644 --- a/services/src/peruser_session.cpp +++ b/services/src/peruser_session.cpp @@ -30,6 +30,7 @@ #include "ipc_skeleton.h" #include "iservice_registry.h" #include "mem_mgr_client.h" +#include "numkey_apps_manager.h" #include "on_demand_start_stop_sa.h" #include "os_account_adapter.h" #include "scene_board_judgement.h" @@ -2220,5 +2221,9 @@ void PerUserSession::ClearRequestKeyboardReason(std::shared_ptr clientInfo->requestKeyboardReason = RequestKeyboardReason::NONE; } +bool PerUserSession::IsNumkeyAutoInputApp(const std::string &bundleName) +{ + return NumkeyAppsManager::GetInstance().NeedAutoNumKeyInput(userId_, bundleName); +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/test/fuzztest/inputmethodability_fuzzer/inputmethodability_fuzzer.cpp b/test/fuzztest/inputmethodability_fuzzer/inputmethodability_fuzzer.cpp index a0b28211c07451450e7876b68c46de9f8d79be91..002874337af20ba50e16b27c975beab377ea46ca 100644 --- a/test/fuzztest/inputmethodability_fuzzer/inputmethodability_fuzzer.cpp +++ b/test/fuzztest/inputmethodability_fuzzer/inputmethodability_fuzzer.cpp @@ -206,7 +206,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) if (!OHOS::InitializeClientInfo(clientInfo)) { return false; } - // auto client = iface_cast(clientInfo.client->AsObject()); auto fuzzedBool = static_cast(data[0] % 2); uint64_t dataValue; diff --git a/test/fuzztest/settingsdatautils_fuzzer/settingsdatautils_fuzzer.cpp b/test/fuzztest/settingsdatautils_fuzzer/settingsdatautils_fuzzer.cpp index c8f31cd5f54f751df61804877982257734261563..b59566984c9ad7ee05b07dbce4434baac001e478 100644 --- a/test/fuzztest/settingsdatautils_fuzzer/settingsdatautils_fuzzer.cpp +++ b/test/fuzztest/settingsdatautils_fuzzer/settingsdatautils_fuzzer.cpp @@ -40,15 +40,15 @@ void FuzzCreateAndRegisterObserver( void FuzzRegisterObserver(const std::string &uriProxy, const std::string &key, SettingsDataObserver::CallbackFunc &func) { - sptr observer = new SettingsDataObserver(key, func); - SettingsDataUtils::GetInstance().RegisterObserver(uriProxy, observer); + sptr observer = new SettingsDataObserver(uriProxy, key, func); + SettingsDataUtils::GetInstance().RegisterObserver(observer); } void FuzzUnregisterObserver( const std::string &uriProxy, const std::string &key, SettingsDataObserver::CallbackFunc &func) { - sptr observer = new SettingsDataObserver(key, func); - SettingsDataUtils::GetInstance().UnregisterObserver(uriProxy, observer); + sptr observer = new SettingsDataObserver(uriProxy, key, func); + SettingsDataUtils::GetInstance().UnregisterObserver(observer); } void FuzzGenerateTargetUri(const std::string &key) diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index eee417974ad0d862be4ffd918d0858d64b277a40..d4bae6eebdef363408761d592130434e65eb5e9e 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -44,6 +44,7 @@ group("unittest") { "cpp_test:InputMethodSwitchTest", "cpp_test:JsonOperateTest", "cpp_test:NewImeSwitchTest", + "cpp_test:NumKeyAppsManagerTest", "cpp_test:OnDemandStartStopSaTest", "cpp_test:StringUtilsTest", "cpp_test:TaskManagerTest", diff --git a/test/unittest/cpp_test/BUILD.gn b/test/unittest/cpp_test/BUILD.gn index 9d47bfab7849adf4d89d720c1d66c0f821ddc63f..e0f84aecddfea67db477cfc99fdb11b9c6906688 100644 --- a/test/unittest/cpp_test/BUILD.gn +++ b/test/unittest/cpp_test/BUILD.gn @@ -1536,3 +1536,40 @@ ohos_unittest("StringUtilsTest") { "hilog:libhilog", ] } + +ohos_unittest("NumKeyAppsManagerTest") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + module_out_path = module_output_path + include_dirs = [ "${inputmethod_path}/common/include" ] + sources = [ "src/numkey_apps_manager_test.cpp" ] + + configs = [ ":module_private_config" ] + deps = [ + "${inputmethod_path}/interfaces/inner_api/inputmethod_controller:inputmethod_client_static", + "${inputmethod_path}/services:inputmethod_service_static", + "${inputmethod_path}/services/adapter/settings_data_provider:settings_data_static", + "${inputmethod_path}/services/file:imf_file_static", + "${inputmethod_path}/services/json:imf_json_static", + "${inputmethod_path}/test/unittest/cpp_test/common:inputmethod_tdd_util", + ] + + external_deps = [ + "ability_base:want", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "config_policy:configpolicy_util", + "data_share:datashare_common", + "data_share:datashare_consumer", + "googletest:gtest_main", + "hilog:libhilog", + "init:libbeget_proxy", + "init:libbegetutil", + "input:libmmi-client", + "resource_management:global_resmgr", + ] +} diff --git a/test/unittest/cpp_test/src/input_method_ability_test.cpp b/test/unittest/cpp_test/src/input_method_ability_test.cpp index 67408d36b6106ed40679e8ba3099fa355942b97f..5d85e8c0e934d2d1106c02c83ff0fc6533f01725 100644 --- a/test/unittest/cpp_test/src/input_method_ability_test.cpp +++ b/test/unittest/cpp_test/src/input_method_ability_test.cpp @@ -18,6 +18,7 @@ #include "input_method_controller.h" #include "input_method_system_ability.h" +#include "key_event_util.h" #include "task_manager.h" #undef private @@ -1732,5 +1733,192 @@ HWTEST_F(InputMethodAbilityTest, testOnSendPrivateData_002, TestSize.Level0) auto ret = InputMethodAbilityTest::inputMethodAbility_.OnSendPrivateData(privateCommand); EXPECT_NE(ret, ErrorCode::NO_ERROR); } + +/** + * @tc.name: testHandleUnconsumedKey_001 + * @tc.desc: Checkout keyEvent is nullptr. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodAbilityTest, testHandleUnconsumedKey_001, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbilityTest testHandleUnconsumedKey_001 START"); + EXPECT_FALSE(InputMethodAbilityTest::inputMethodAbility_.HandleUnconsumedKey(nullptr)); +} + +/** + * @tc.name: testHandleUnconsumedKey_002 + * @tc.desc: Checkout GetInputDataChannelProxy is nullptr. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodAbilityTest, testHandleUnconsumedKey_002, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbilityTest testHandleUnconsumedKey_002 START"); + + InputMethodAbilityTest::inputMethodAbility_.ClearDataChannel( + InputMethodAbilityTest::inputMethodAbility_.dataChannelObject_); + std::shared_ptr keyEvent = MMI::KeyEvent::Create(); + EXPECT_FALSE(inputMethodAbility_.HandleUnconsumedKey(keyEvent)); +} + +/** + * @tc.name: testHandleUnconsumedKey_003 + * @tc.desc: Checkout InputMethodAbility.needAutoInputNumkey is false. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodAbilityTest, testHandleUnconsumedKey_003, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbilityTest testHandleUnconsumedKey_003 START"); + InputMethodAbilityTest::GetIMCAttachIMA(); + inputMethodAbility_.inputAttribute_.needAutoInputNumkey = false; + std::shared_ptr keyEvent = MMI::KeyEvent::Create(); + EXPECT_FALSE(inputMethodAbility_.HandleUnconsumedKey(keyEvent)); + InputMethodAbilityTest::GetIMCDetachIMA(); +} + +/** + * @tc.name: testHandleUnconsumedKey_004 + * @tc.desc: Checkout the keyEvent is not down key. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodAbilityTest, testHandleUnconsumedKey_004, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbilityTest testHandleUnconsumedKey_004 START"); + InputMethodAbilityTest::GetIMCAttachIMA(); + inputMethodAbility_.inputAttribute_.needAutoInputNumkey = true; + auto keyEvent = KeyEventUtil::CreateKeyEvent(MMI::KeyEvent::KEYCODE_A, MMI::KeyEvent::KEY_ACTION_UP); + EXPECT_FALSE(InputMethodAbility::GetInstance().HandleUnconsumedKey(keyEvent)); + InputMethodAbilityTest::GetIMCDetachIMA(); +} + +/** + * @tc.name: testHandleUnconsumedKey_005 + * @tc.desc: Checkout only handle single key. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodAbilityTest, testHandleUnconsumedKey_005, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbilityTest testHandleUnconsumedKey_005 START"); + InputMethodAbilityTest::GetIMCAttachIMA(); + inputMethodAbility_.inputAttribute_.needAutoInputNumkey = true; + auto keyEvent = KeyEventUtil::CreateKeyEvent(MMI::KeyEvent::KEYCODE_0, MMI::KeyEvent::KEY_ACTION_DOWN); + ASSERT_TRUE(keyEvent != nullptr); + MMI::KeyEvent::KeyItem keyItem; + keyItem.SetKeyCode(MMI::KeyEvent::KEYCODE_A); + keyItem.SetPressed(true); + keyEvent->AddPressedKeyItems(keyItem); + EXPECT_FALSE(inputMethodAbility_.HandleUnconsumedKey(keyEvent)); + InputMethodAbilityTest::GetIMCDetachIMA(); +} + +/** + * @tc.name: testHandleUnconsumedKey_006 + * @tc.desc: Checkout KEYCODE_0 to KEYCODE_9. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodAbilityTest, testHandleUnconsumedKey_006, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbilityTest testHandleUnconsumedKey_006 START"); + InputMethodAbilityTest::GetIMCAttachIMA(); + inputMethodAbility_.inputAttribute_.needAutoInputNumkey = true; + auto keyEvent = KeyEventUtil::CreateKeyEvent(MMI::KeyEvent::KEYCODE_6, MMI::KeyEvent::KEY_ACTION_DOWN); + EXPECT_TRUE(InputMethodAbility::GetInstance().HandleUnconsumedKey(keyEvent)); +} + +/** + * @tc.name: testHandleUnconsumedKey_007 + * @tc.desc: Checkout the GetFunctionKey. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodAbilityTest, testHandleUnconsumedKey_007, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbilityTest testHandleUnconsumedKey_007 START"); + InputMethodAbilityTest::GetIMCAttachIMA(); + inputMethodAbility_.inputAttribute_.needAutoInputNumkey = true; + + auto keyEvent = KeyEventUtil::CreateKeyEvent(MMI::KeyEvent::KEYCODE_NUMPAD_0, MMI::KeyEvent::KEY_ACTION_DOWN); + ASSERT_TRUE(keyEvent != nullptr); + keyEvent->SetFunctionKey(MMI::KeyEvent::NUM_LOCK_FUNCTION_KEY, 0); + EXPECT_FALSE(inputMethodAbility_.HandleUnconsumedKey(keyEvent)); + InputMethodAbilityTest::GetIMCDetachIMA(); +} + +/** + * @tc.name: testHandleUnconsumedKey_008 + * @tc.desc: Checkout KEYCODE_NUMPAD_0 to KEYCODE_NUMPAD_9. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodAbilityTest, testHandleUnconsumedKey_008, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbilityTest testHandleUnconsumedKey_008 START"); + + sptr channelObject = new InputDataChannelServiceImpl(); + auto channelProxy = std::make_shared(channelObject->AsObject()); + InputMethodAbility::GetInstance().dataChannelProxy_ = channelProxy; + InputMethodAbility::GetInstance().inputAttribute_.needAutoInputNumkey = true; + + auto keyEvent = KeyEventUtil::CreateKeyEvent(MMI::KeyEvent::KEYCODE_NUMPAD_0, MMI::KeyEvent::KEY_ACTION_DOWN); + keyEvent->SetFunctionKey(MMI::KeyEvent::NUM_LOCK_FUNCTION_KEY, true); + auto ret = InputMethodAbility::GetInstance().HandleUnconsumedKey(keyEvent); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: testHandleUnconsumedKey_009 + * @tc.desc: Checkout the serialization of InputAttribute. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodAbilityTest, testHandleUnconsumedKey_009, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbilityTest testHandleUnconsumedKey_009 START"); + sptr channelObject = new InputDataChannelServiceImpl(); + auto channelProxy = std::make_shared(channelObject->AsObject()); + InputMethodAbility::GetInstance().dataChannelProxy_ = channelProxy; + InputMethodAbility::GetInstance().inputAttribute_.needAutoInputNumkey = true; + + auto keyEvent = KeyEventUtil::CreateKeyEvent(MMI::KeyEvent::KEYCODE_A, MMI::KeyEvent::KEY_ACTION_DOWN); + EXPECT_FALSE(InputMethodAbility::GetInstance().HandleUnconsumedKey(keyEvent)); +} + +/** + * @tc.name: testHandleUnconsumedKey_010 + * @tc.desc: Checkout < KEYCODE_0 or > KEYCODE_9. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodAbilityTest, testHandleUnconsumedKey_010, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbilityTest testHandleUnconsumedKey_010 START"); + InputMethodAbilityTest::GetIMCAttachIMA(); + inputMethodAbility_.inputAttribute_.needAutoInputNumkey = true; + + int32_t keyCode = MMI::KeyEvent::KEYCODE_0 - 1; + auto keyEvent = KeyEventUtil::CreateKeyEvent(keyCode, MMI::KeyEvent::KEY_ACTION_DOWN); + EXPECT_FALSE(InputMethodAbility::GetInstance().HandleUnconsumedKey(keyEvent)); + + keyCode = MMI::KeyEvent::KEYCODE_9 + 1; + keyEvent = KeyEventUtil::CreateKeyEvent(keyCode, MMI::KeyEvent::KEY_ACTION_DOWN); + EXPECT_FALSE(InputMethodAbility::GetInstance().HandleUnconsumedKey(keyEvent)); + InputMethodAbilityTest::GetIMCDetachIMA(); +} + +/** + * @tc.name: testHandleUnconsumedKey_011 + * @tc.desc: Checkout < KEYCODE_NUMPAD_0 or > KEYCODE_NUMPAD_9. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodAbilityTest, testHandleUnconsumedKey_011, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbilityTest testHandleUnconsumedKey_011 START"); + InputMethodAbilityTest::GetIMCAttachIMA(); + inputMethodAbility_.inputAttribute_.needAutoInputNumkey = true; + + int32_t keyCode = MMI::KeyEvent::KEYCODE_NUMPAD_0 - 1; + auto keyEvent = KeyEventUtil::CreateKeyEvent(keyCode, MMI::KeyEvent::KEY_ACTION_DOWN); + EXPECT_FALSE(InputMethodAbility::GetInstance().HandleUnconsumedKey(keyEvent)); + + keyCode = MMI::KeyEvent::KEYCODE_NUMPAD_9 + 1; + keyEvent = KeyEventUtil::CreateKeyEvent(keyCode, MMI::KeyEvent::KEY_ACTION_DOWN); + EXPECT_FALSE(InputMethodAbility::GetInstance().HandleUnconsumedKey(keyEvent)); + InputMethodAbilityTest::GetIMCDetachIMA(); +} } // namespace MiscServices } // namespace OHOS diff --git a/test/unittest/cpp_test/src/input_method_private_member_test.cpp b/test/unittest/cpp_test/src/input_method_private_member_test.cpp index d4a29a920b12220c3bd0d1a34aeb0e091af17118..ed38afd22ff835ded8db674c6ca8f3aa35a80b21 100644 --- a/test/unittest/cpp_test/src/input_method_private_member_test.cpp +++ b/test/unittest/cpp_test/src/input_method_private_member_test.cpp @@ -1395,7 +1395,7 @@ HWTEST_F(InputMethodPrivateMemberTest, BranchCoverage004, TestSize.Level0) std::shared_ptr helper; std::string invaildString; pid_t pid { -1 }; - auto ret = SettingsDataUtils::GetInstance().RegisterObserver(invaildString, observer); + auto ret = SettingsDataUtils::GetInstance().RegisterObserver(observer); EXPECT_EQ(ret, ErrorCode::ERROR_NULL_POINTER); ret = SettingsDataUtils::GetInstance().GetStringValue(invaildString, invaildString, invaildString); EXPECT_EQ(ret, ErrorCode::ERROR_NULL_POINTER); diff --git a/test/unittest/cpp_test/src/numkey_apps_manager_test.cpp b/test/unittest/cpp_test/src/numkey_apps_manager_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b98699b0d8bce4eb555aef02849f4887219f2b48 --- /dev/null +++ b/test/unittest/cpp_test/src/numkey_apps_manager_test.cpp @@ -0,0 +1,333 @@ +/* + * Copyright (C) 2025 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. + */ + +#define private public +#define protected public +#include "numkey_apps_manager.h" + +#include "ime_info_inquirer.h" + +#undef private + +#include + +using namespace testing::ext; +namespace OHOS { +namespace MiscServices { +class NumKeyAppsManagerTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + +private: +}; + +constexpr std::int32_t MAIN_USER_ID = 100; +constexpr std::int32_t INVALID_USER_ID = 10001; +static constexpr const char *WHITE_LIST_APP_NAME = "WHITE_LIST_APP_NAME"; +static constexpr const char *BLOCK_LIST_APP_NAME = "BLOCK_LIST_APP_NAME"; + +void NumKeyAppsManagerTest::SetUpTestCase(void) +{ + IMSA_HILOGI("NumKeyAppsManagerTest::SetUpTestCase"); +} + +void NumKeyAppsManagerTest::TearDownTestCase(void) +{ + IMSA_HILOGI("NumKeyAppsManagerTest::TearDownTestCase"); +} + +void NumKeyAppsManagerTest::SetUp() +{ + IMSA_HILOGI("NumKeyAppsManagerTest::SetUp"); +} + +void NumKeyAppsManagerTest::TearDown() +{ + IMSA_HILOGI("NumKeyAppsManagerTest::TearDown"); +} + +/** + * @tc.name: testFeatureNotEnabled_001 + * @tc.desc: when feature not enabled + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testFeatureNotEnabled_001, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testFeatureNotEnabled_001 START"); + NumkeyAppsManager::GetInstance().isFeatureEnabled_ = false; + ImeInfoInquirer::GetInstance().systemConfig_.enableNumKeyFeature = false; + int32_t ret = NumkeyAppsManager::GetInstance().Init(MAIN_USER_ID); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + EXPECT_EQ(NumkeyAppsManager::GetInstance().usersBlockList_.find(MAIN_USER_ID), + NumkeyAppsManager::GetInstance().usersBlockList_.end()); + ret = NumkeyAppsManager::GetInstance().NeedAutoNumKeyInput(MAIN_USER_ID, WHITE_LIST_APP_NAME); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + ret = NumkeyAppsManager::GetInstance().OnUserSwitched(MAIN_USER_ID); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + ret = NumkeyAppsManager::GetInstance().OnUserRemoved(MAIN_USER_ID); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); +} + +/** + * @tc.name: testInit_001 + * @tc.desc: test init when feature enabled + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testInit_001, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testInit_001 START"); + NumkeyAppsManager::GetInstance().isFeatureEnabled_ = true; + ImeInfoInquirer::GetInstance().systemConfig_.enableNumKeyFeature = true; + int32_t ret = NumkeyAppsManager::GetInstance().Init(MAIN_USER_ID); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + EXPECT_NE(NumkeyAppsManager::GetInstance().usersBlockList_.find(MAIN_USER_ID), + NumkeyAppsManager::GetInstance().usersBlockList_.end()); +} + +/** + * @tc.name: testNeedAutoNumKeyInput_001 + * @tc.desc: test NeedAutoNumKeyInput when numKeyAppList_ empty or not empty + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testNeedAutoNumKeyInput_001, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testNeedAutoNumKeyInput_001 START"); + NumkeyAppsManager::GetInstance().isFeatureEnabled_ = true; + + NumkeyAppsManager::GetInstance().numKeyAppList_.clear(); + bool ret = NumkeyAppsManager::GetInstance().NeedAutoNumKeyInput(MAIN_USER_ID, WHITE_LIST_APP_NAME); + EXPECT_FALSE(ret); + + NumkeyAppsManager::GetInstance().numKeyAppList_.insert(WHITE_LIST_APP_NAME); + NumkeyAppsManager::GetInstance().usersBlockList_.clear(); + ret = NumkeyAppsManager::GetInstance().NeedAutoNumKeyInput(MAIN_USER_ID, WHITE_LIST_APP_NAME); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: testNeedAutoNumKeyInput_002 + * @tc.desc: test NeedAutoNumKeyInput when numKeyAppList_ not empty, usersBlockList_ empty or not empty + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testNeedAutoNumKeyInput_002, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testNeedAutoNumKeyInput_002 START"); + NumkeyAppsManager::GetInstance().isFeatureEnabled_ = true; + NumkeyAppsManager::GetInstance().numKeyAppList_.insert(WHITE_LIST_APP_NAME); + + NumkeyAppsManager::GetInstance().usersBlockList_.clear(); + bool ret = NumkeyAppsManager::GetInstance().NeedAutoNumKeyInput(MAIN_USER_ID, WHITE_LIST_APP_NAME); + EXPECT_TRUE(ret); + + NumkeyAppsManager::GetInstance().usersBlockList_[MAIN_USER_ID] = { BLOCK_LIST_APP_NAME }; + ret = NumkeyAppsManager::GetInstance().NeedAutoNumKeyInput(MAIN_USER_ID, WHITE_LIST_APP_NAME); + EXPECT_TRUE(ret); + + NumkeyAppsManager::GetInstance().usersBlockList_[MAIN_USER_ID] = { BLOCK_LIST_APP_NAME }; + ret = NumkeyAppsManager::GetInstance().NeedAutoNumKeyInput(MAIN_USER_ID, BLOCK_LIST_APP_NAME); + EXPECT_FALSE(ret); + + NumkeyAppsManager::GetInstance().numKeyAppList_.clear(); + NumkeyAppsManager::GetInstance().usersBlockList_.clear(); +} + +/** + * @tc.name: testOnUserSwitched_001 + * @tc.desc: already inited, no need to update when user switch + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testOnUserSwitched_001, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testOnUserSwitched_001 START"); + NumkeyAppsManager::GetInstance().isFeatureEnabled_ = true; + NumkeyAppsManager::GetInstance().usersBlockList_[MAIN_USER_ID] = { BLOCK_LIST_APP_NAME }; + auto ret = NumkeyAppsManager::GetInstance().OnUserSwitched(MAIN_USER_ID); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + EXPECT_EQ(NumkeyAppsManager::GetInstance().usersBlockList_[MAIN_USER_ID].size(), 1); + EXPECT_TRUE(NumkeyAppsManager::GetInstance().usersBlockList_[MAIN_USER_ID].count(BLOCK_LIST_APP_NAME) > 0); +} + +/** + * @tc.name: testOnUserSwitched_002 + * @tc.desc: update usersblocklist with user not inited when user switched + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testOnUserSwitched_002, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testOnUserSwitched_002 START"); + NumkeyAppsManager::GetInstance().isFeatureEnabled_ = true; + NumkeyAppsManager::GetInstance().usersBlockList_.clear(); + auto ret = NumkeyAppsManager::GetInstance().OnUserSwitched(MAIN_USER_ID); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + EXPECT_NE(NumkeyAppsManager::GetInstance().usersBlockList_.find(MAIN_USER_ID), + NumkeyAppsManager::GetInstance().usersBlockList_.end()); +} + +/** + * @tc.name: testOnUserSwitched_003 + * @tc.desc: test usersBlockList_ not empty after OnUserSwitched + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testOnUserSwitched_003, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testOnUserSwitched_003 START"); + NumkeyAppsManager::GetInstance().usersBlockList_.clear(); + auto ret = NumkeyAppsManager::GetInstance().OnUserSwitched(MAIN_USER_ID); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + bool result = NumkeyAppsManager::GetInstance().usersBlockList_.find(MAIN_USER_ID) + != NumkeyAppsManager::GetInstance().usersBlockList_.end(); + EXPECT_TRUE(result); +} + +/** + * @tc.name: testOnUserRemoved_001 + * @tc.desc: user removed when observers empty + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testOnUserRemoved_001, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testOnUserRemoved_001 START"); + NumkeyAppsManager::GetInstance().isFeatureEnabled_ = true; + NumkeyAppsManager::GetInstance().observers_.clear(); + auto ret = NumkeyAppsManager::GetInstance().OnUserRemoved(MAIN_USER_ID); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); +} + +/** + * @tc.name: testOnUserRemoved_002 + * @tc.desc: observers_ not empty, remove valid user + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testOnUserRemoved_002, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testOnUserRemoved_002 START"); + NumkeyAppsManager::GetInstance().isFeatureEnabled_ = true; + sptr observer = new (std::nothrow) SettingsDataObserver("", "", nullptr); + ASSERT_TRUE(observer != nullptr); + NumkeyAppsManager::GetInstance().observers_.clear(); + NumkeyAppsManager::GetInstance().observers_[MAIN_USER_ID] = observer; + NumkeyAppsManager::GetInstance().OnUserRemoved(MAIN_USER_ID); + EXPECT_EQ(NumkeyAppsManager::GetInstance().observers_.find(MAIN_USER_ID), + NumkeyAppsManager::GetInstance().observers_.end()); + NumkeyAppsManager::GetInstance().observers_.clear(); +} + +/** + * @tc.name: testOnUserRemoved_003 + * @tc.desc: observers_ not empty, remove invalid user + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testOnUserRemoved_003, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testOnUserRemoved_003 START"); + NumkeyAppsManager::GetInstance().isFeatureEnabled_ = true; + sptr observer = new (std::nothrow) SettingsDataObserver("", "", nullptr); + ASSERT_TRUE(observer != nullptr); + NumkeyAppsManager::GetInstance().observers_.clear(); + NumkeyAppsManager::GetInstance().observers_[MAIN_USER_ID] = observer; + NumkeyAppsManager::GetInstance().OnUserRemoved(INVALID_USER_ID); + EXPECT_NE(NumkeyAppsManager::GetInstance().observers_.find(MAIN_USER_ID), + NumkeyAppsManager::GetInstance().observers_.end()); + NumkeyAppsManager::GetInstance().observers_.clear(); +} + +/** + * @tc.name: testInitWhiteList_001 + * @tc.desc: InitWhiteList when already inited + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testInitWhiteList_001, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testInitWhiteList_001 START"); + bool inited = NumkeyAppsManager::GetInstance().isListInited_.load(); + NumkeyAppsManager::GetInstance().isListInited_.store(true); + auto ret = NumkeyAppsManager::GetInstance().InitWhiteList(); + NumkeyAppsManager::GetInstance().isListInited_.store(inited); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); +} + +/** + * @tc.name: testInitWhiteList_002 + * @tc.desc: InitWhiteList when not inited + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testInitWhiteList_002, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testInitWhiteList_002 START"); + bool inited = NumkeyAppsManager::GetInstance().isListInited_.load(); + NumkeyAppsManager::GetInstance().isListInited_.store(false); + auto ret = NumkeyAppsManager::GetInstance().InitWhiteList(); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + NumkeyAppsManager::GetInstance().isListInited_.store(inited); +} + +/** + * @tc.name: testUpdateUserBlockList_001 + * @tc.desc: usersBlockList_ not empty update user block list + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testUpdateUserBlockList_001, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testUpdateUserBlockList_001 START"); + NumkeyAppsManager::GetInstance().usersBlockList_.clear(); + auto ret = NumkeyAppsManager::GetInstance().UpdateUserBlockList(MAIN_USER_ID); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + EXPECT_NE(NumkeyAppsManager::GetInstance().usersBlockList_.find(MAIN_USER_ID), + NumkeyAppsManager::GetInstance().usersBlockList_.end()); + NumkeyAppsManager::GetInstance().usersBlockList_.clear(); +} + +/** + * @tc.name: testParseWhiteList_001 + * @tc.desc: test ParseWhiteList + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testParseWhiteList_001, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testParseWhiteList_001 START"); + std::unordered_set list; + auto ret = NumkeyAppsManager::GetInstance().ParseWhiteList(list); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); +} + +/** + * @tc.name: testParseBlockList_001 + * @tc.desc: test ParseBlockList + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testParseBlockList_001, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testParseBlockList_001 START"); + std::unordered_set list; + auto ret = NumkeyAppsManager::GetInstance().ParseBlockList(MAIN_USER_ID, list); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); +} + +/** + * @tc.name: testRegisterUserBlockListData_001 + * @tc.desc: test RegisterUserBlockListData + * @tc.type: FUNC + */ +HWTEST_F(NumKeyAppsManagerTest, testRegisterUserBlockListData_001, TestSize.Level1) +{ + IMSA_HILOGI("NumKeyAppsManagerTest testRegisterUserBlockListData_001 START"); + auto ret = NumkeyAppsManager::GetInstance().RegisterUserBlockListData(MAIN_USER_ID); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); +} +} // namespace MiscServices +} // namespace OHOS