diff --git a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp index 588cd483..58d8856c 100644 --- a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp +++ b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp @@ -45,7 +45,10 @@ const std::unordered_map EVENT_TYPE{ { "imeChange", IME_ InputMethodController::InputMethodController() : stop_(false) { IMSA_HILOGI("InputMethodController structure"); - Initialize(); + int32_t ret = Initialize(); + if (ret != ErrorCode::NO_ERROR) { + InputMethodSysEvent::InputmethodFaultReporter(ret, "", "IMC initialize failed!"); + } } InputMethodController::~InputMethodController() @@ -118,24 +121,24 @@ void InputMethodController::SetControllerListener(std::shared_ptrSetHandler(msgHandler_); auto channel = new (std::nothrow) InputDataChannelStub(); if (channel == nullptr) { IMSA_HILOGE("failed to new channel"); - return false; + return ErrorCode::ERROR_NULL_POINTER; } channel->SetHandler(msgHandler_); InputAttribute attribute = { .inputPattern = InputAttribute::PATTERN_TEXT }; @@ -144,7 +147,7 @@ bool InputMethodController::Initialize() // make AppExecFwk::EventHandler handler handler_ = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); - return true; + return ErrorCode::NO_ERROR; } sptr InputMethodController::GetSystemAbilityProxy() diff --git a/hisysevent.yaml b/hisysevent.yaml index 743d4fc2..ad63535f 100644 --- a/hisysevent.yaml +++ b/hisysevent.yaml @@ -14,22 +14,22 @@ domain: INPUTMETHOD SERVICE_INIT_FAILED: - __BASE: {type: STATISTIC, level: CRITICAL, tag: IMFServiceFailed, desc: Inputmethod service init report} + __BASE: {type: FAULT, level: CRITICAL, tag: IMFServiceFailed, desc: Inputmethod service init report} USER_ID: {type: INT32, desc: The user id} - COMPONENT_ID: {type: INT32, desc: Component type} + COMPONENT_ID: {type: STRING, desc: Component name} ERROR_CODE: {type: INT32, desc: Error code} -CREATE_COMPONENT_FAILED: - __BASE: {type: STATISTIC, level: CRITICAL, tag: IMCFailed, desc: Create component failed report} +INPUTMETHOD_UNAVAILABLE: + __BASE: {type: FAULT, level: CRITICAL, tag: IMEUnavaliable, desc: inputmethod unavailable} USER_ID: {type: INT32, desc: The user id} - COMPONENT_ID: {type: INT32, desc: The component type} + APP_NAME: {type: STRING, desc: app name} ERROR_CODE: {type: INT32, desc: Error code} + INFO: {type: STRING, desc: Error information} -INPUTMETHOD_USING: +IME_USAGE: __BASE: {type: STATISTIC, level: MINOR, tag: IMEUsage, desc: inputmethod using report} - USER_ID: {type: INT32, desc: the timer id} - COMPONENT_ID: {type: INT32,desc: the component type} - ERROR_CODE: {type: INT32, desc: error code} + IME_START: {type: INT32, desc: the number of ime starts} + IME_CHANGE: {type: INT32, desc: the number of ime switchs} OPERATE_SOFTKEYBOARD: __BASE: {type: BEHAVIOR, level: MINOR, tag: IMEOperate, desc: Operate the soft keyboard report} diff --git a/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h b/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h index fb0727d4..f0196aa4 100644 --- a/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h +++ b/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h @@ -433,7 +433,7 @@ private: InputMethodController(); ~InputMethodController(); - bool Initialize(); + int32_t Initialize(); sptr GetSystemAbilityProxy(); int32_t PrepareInput(InputClientInfo &inputClientInfo); int32_t StartInput(sptr &client, bool isShowKeyboard, bool attachFlag); diff --git a/services/dfx/include/inputmethod_sysevent.h b/services/dfx/include/inputmethod_sysevent.h index ae575957..cdd5cc9e 100644 --- a/services/dfx/include/inputmethod_sysevent.h +++ b/services/dfx/include/inputmethod_sysevent.h @@ -16,10 +16,13 @@ #ifndef INPUTMETHOD_SYSEVENT_H #define INPUTMETHOD_SYSEVENT_H +#include +#include #include #include #include "global.h" +#include "timer.h" namespace OHOS { namespace MiscServices { @@ -35,19 +38,45 @@ enum OperateIMEInfoCode : int32_t { IME_HIDE_SELF, }; +enum IMEBehaviour : int32_t { + START_IME = 0, + CHANGE_IME, +}; + class InputMethodSysEvent { public: - static void FaultReporter(int32_t userId, const std::string &bundleName, int32_t errCode); - static void CreateComponentFailed(int32_t userId, int32_t errCode); - static void BehaviourReporter(const std::string &activeName, const std::string &inputMethodName); + static void ServiceFaultReporter(const std::string &bundleName, int32_t errCode); + static void InputmethodFaultReporter(int32_t errCode, const std::string &name, const std::string &info); + static void EventRecorder(IMEBehaviour behaciour); static void OperateSoftkeyboardBehaviour(OperateIMEInfoCode infoCode); + static void StartTimerForReport(); + static void SetUserId(int32_t userId); private: + using TimerCallback = std::function; + static void ImeUsageBehaviourReporter(); static const std::string GetOperateInfo(OperateIMEInfoCode infoCode); static std::string GetOperateAction(OperateIMEInfoCode infoCode); + static void StartTimer(const TimerCallback &callback, uint32_t interval); + static void StopTimer(); + static int32_t GetReportTime(); private: static const std::unordered_map operateInfo_; + static std::map inputmethodBehaviour_; + static std::mutex behaviourMutex_; + + static Utils::Timer timer_; + static int32_t userId_; + static uint32_t timerId_; + static std::mutex timerLock_; + static bool isTimerStart_; + static inline constexpr int32_t ONE_DAY_IN_HOURS = 24; + static inline constexpr int32_t EXEC_HOUR_TIME = 23; + static inline constexpr int32_t EXEC_MIN_TIME = 60; + static inline constexpr int32_t ONE_MINUTE_IN_SECONDS = 60; + static inline constexpr int32_t ONE_HOUR_IN_SECONDS = 1 * 60 * 60; // 1 hour + static inline constexpr int32_t SECONDS_TO_MILLISECONDS = 1000; }; } // namespace MiscServices } // namespace OHOS diff --git a/services/dfx/src/inputmethod_sysevent.cpp b/services/dfx/src/inputmethod_sysevent.cpp index b0069fca..f32912f5 100644 --- a/services/dfx/src/inputmethod_sysevent.cpp +++ b/services/dfx/src/inputmethod_sysevent.cpp @@ -15,10 +15,11 @@ #include "inputmethod_sysevent.h" -#include "hisysevent.h" - #include +#include "common_timer_errors.h" +#include "hisysevent.h" + namespace OHOS { namespace MiscServices { namespace { @@ -37,31 +38,60 @@ const std::unordered_map InputMethodSysEvent::operateInfo_ {IME_HIDE_SELF, "HideKeyboardSelf: hide soft keyboard self."} }; -void InputMethodSysEvent::FaultReporter(int32_t userId, const std::string &bundleName, int32_t errCode) +std::map InputMethodSysEvent::inputmethodBehaviour_ = { + {START_IME, 0}, + {CHANGE_IME, 0} +}; + +Utils::Timer InputMethodSysEvent::timer_("imfTimer"); +uint32_t InputMethodSysEvent::timerId_(0); +std::mutex InputMethodSysEvent::behaviourMutex_; +std::mutex InputMethodSysEvent::timerLock_; +bool InputMethodSysEvent::isTimerStart_ = false; +int32_t InputMethodSysEvent::userId_ = 0; + +void InputMethodSysEvent::ServiceFaultReporter(const std::string &bundleName, int32_t errCode) { int32_t ret = HiSysEventWrite(HiSysEventNameSpace::Domain::INPUTMETHOD, "SERVICE_INIT_FAILED", - HiSysEventNameSpace::EventType::FAULT, "USER_ID", userId, "COMPONENT_ID", bundleName, "ERROR_CODE", errCode); + HiSysEventNameSpace::EventType::FAULT, "USER_ID", userId_, "COMPONENT_ID", bundleName, "ERROR_CODE", errCode); if (ret != HiviewDFX::SUCCESS) { - IMSA_HILOGE("hisysevent FaultReporter failed! ret %{public}d,errCode %{public}d", ret, errCode); + IMSA_HILOGE("hisysevent ServiceFaultReporter failed! ret %{public}d,errCode %{public}d", ret, errCode); } } -void InputMethodSysEvent::CreateComponentFailed(int32_t userId, int32_t errCode) +void InputMethodSysEvent::InputmethodFaultReporter(int32_t errCode, const std::string &name, const std::string &info) { - int32_t ret = HiSysEventWrite(HiSysEventNameSpace::Domain::INPUTMETHOD, "CREATE_COMPONENT_FAILED", - HiSysEventNameSpace::EventType::FAULT, "USER_ID", userId, "ERROR_CODE", errCode); + int32_t ret = HiSysEventWrite(HiSysEventNameSpace::Domain::INPUTMETHOD, "INPUTMETHOD_UNAVAILABLE", + HiSysEventNameSpace::EventType::FAULT, "USER_ID", userId_, "APP_NAME", name, "ERROR_CODE", errCode, "INFO", + info); if (ret != HiviewDFX::SUCCESS) { - IMSA_HILOGE("hisysevent CreateComponentFailed failed! ret %{public}d,errCode %{public}d", ret, errCode); + IMSA_HILOGE("hisysevent InputmethodFaultReporter failed! ret %{public}d,errCode %{public}d", ret, errCode); } } -void InputMethodSysEvent::BehaviourReporter(const std::string &activeName, const std::string &inputMethodName) +void InputMethodSysEvent::ImeUsageBehaviourReporter() { - int32_t ret = HiSysEventWrite(HiSysEventNameSpace::Domain::INPUTMETHOD, "INPUTMETHOD_USING", - HiSysEventNameSpace::EventType::BEHAVIOR, "ACTIVE_NAME", activeName, "INPUTMETHOD_NAME", inputMethodName); + IMSA_HILOGE("msy ImeUsageBehaviourReporter"); + std::lock_guard lock(behaviourMutex_); + int ret = HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::INPUTMETHOD, "IME_USAGE", + HiSysEventNameSpace::EventType::STATISTIC, "IME_START", inputmethodBehaviour_[START_IME], "IME_CHANGE", + inputmethodBehaviour_[CHANGE_IME]); if (ret != HiviewDFX::SUCCESS) { IMSA_HILOGE("hisysevent BehaviourReporter failed! ret %{public}d", ret); } + inputmethodBehaviour_[START_IME] = 0; + inputmethodBehaviour_[CHANGE_IME] = 0; + StartTimerForReport(); +} + +void InputMethodSysEvent::EventRecorder(IMEBehaviour behaviour) +{ + std::lock_guard lock(behaviourMutex_); + if (behaviour == IMEBehaviour::START_IME) { + inputmethodBehaviour_[START_IME]++; + } else if (behaviour == IMEBehaviour::CHANGE_IME) { + inputmethodBehaviour_[CHANGE_IME]++; + } } void InputMethodSysEvent::OperateSoftkeyboardBehaviour(OperateIMEInfoCode infoCode) @@ -104,5 +134,77 @@ std::string InputMethodSysEvent::GetOperateAction(OperateIMEInfoCode infoCode) } return "unknow action."; } + +void InputMethodSysEvent::SetUserId(int32_t userId) +{ + userId_ = userId; +} + +void InputMethodSysEvent::StartTimer(const TimerCallback &callback, uint32_t interval) +{ + IMSA_HILOGD("run in"); + isTimerStart_ = true; + uint32_t ret = timer_.Setup(); + if (ret != Utils::TIMER_ERR_OK) { + IMSA_HILOGE("Create Timer error"); + return; + } + timerId_ = timer_.Register(callback, interval, true); +} + +void InputMethodSysEvent::StopTimer() +{ + IMSA_HILOGD("run in"); + timer_.Unregister(timerId_); + timer_.Shutdown(); + isTimerStart_ = false; +} + +void InputMethodSysEvent::StartTimerForReport() +{ + IMSA_HILOGD("run in"); + auto reportCallback = []() { ImeUsageBehaviourReporter(); }; + std::lock_guard lock(timerLock_); + if (isTimerStart_) { + IMSA_HILOGD("isTimerStart_ is true. Update timer."); + timer_.Unregister(timerId_); + timerId_ = + timer_.Register(reportCallback, ONE_DAY_IN_HOURS * ONE_HOUR_IN_SECONDS * SECONDS_TO_MILLISECONDS, false); + } else { + int32_t interval = GetReportTime(); + if (interval >= 0) { + StartTimer(reportCallback, interval); + } + } +} + +int32_t InputMethodSysEvent::GetReportTime() +{ + IMSA_HILOGD("GetReportTime run in."); + time_t current = time(nullptr); + if (current == -1) { + IMSA_HILOGE("Get current time failed!"); + return -1; + } + tm localTime = { 0 }; + tm *result = localtime_r(¤t, &localTime); + if (result == nullptr) { + IMSA_HILOGE("Get local time failed!"); + return -1; + } + int32_t currentHour = localTime.tm_hour; + int32_t currentMin = localTime.tm_min; + IMSA_HILOGD("get"); + if ((EXEC_MIN_TIME - currentMin) != EXEC_MIN_TIME) { + int32_t nHours = EXEC_HOUR_TIME - currentHour; + int32_t nMin = EXEC_MIN_TIME - currentMin; + int32_t nTime = (nMin)*ONE_MINUTE_IN_SECONDS + (nHours)*ONE_HOUR_IN_SECONDS; + IMSA_HILOGD( + " StartTimerThread if needHours=%{public}d,needMin=%{public}d,needTime=%{public}d", nHours, nMin, nTime); + return nTime * SECONDS_TO_MILLISECONDS; + } else { + return ONE_HOUR_IN_SECONDS * (ONE_DAY_IN_HOURS - currentHour) * SECONDS_TO_MILLISECONDS; + } +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/services/src/input_method_system_ability.cpp b/services/src/input_method_system_ability.cpp index a587783e..b485712a 100644 --- a/services/src/input_method_system_ability.cpp +++ b/services/src/input_method_system_ability.cpp @@ -73,13 +73,16 @@ InputMethodSystemAbility::~InputMethodSystemAbility() void InputMethodSystemAbility::OnStart() { IMSA_HILOGI("InputMethodSystemAbility::OnStart."); + InputMethodSysEvent::StartTimerForReport(); if (state_ == ServiceRunningState::STATE_RUNNING) { IMSA_HILOGI("ImsaService is already running."); return; } Initialize(); InitServiceHandler(); - if (Init() != ErrorCode::NO_ERROR) { + int32_t ret = Init(); + if (ret != ErrorCode::NO_ERROR) { + InputMethodSysEvent::ServiceFaultReporter("imf", ret); auto callback = [=]() { Init(); }; serviceHandler_->PostTask(callback, INIT_INTERVAL); IMSA_HILOGE("Init failed. Try again 10s later"); @@ -138,6 +141,7 @@ int32_t InputMethodSystemAbility::Init() return OsAccountManager::QueryActiveOsAccountIds(userIds) == ERR_OK && !userIds.empty(); })) { userId_ = userIds[0]; + InputMethodSysEvent::SetUserId(userId_); userSession_->UpdateCurrentUserId(userId_); } StartUserIdListener(); @@ -289,7 +293,6 @@ int32_t InputMethodSystemAbility::SetCoreAndAgent(sptr core, s return ErrorCode::ERROR_NOT_CURRENT_IME; } if (core == nullptr || agent == nullptr) { - InputMethodSysEvent::CreateComponentFailed(userId_, ErrorCode::ERROR_NULL_POINTER); IMSA_HILOGE("InputMethodSystemAbility::core or agent is nullptr"); return ErrorCode::ERROR_NULL_POINTER; } @@ -366,6 +369,7 @@ int32_t InputMethodSystemAbility::SwitchInputMethod(const std::string &bundleNam int32_t InputMethodSystemAbility::OnSwitchInputMethod(const SwitchInfo &switchInfo, bool isCheckPermission) { IMSA_HILOGD("run in, switchInfo: %{public}s|%{public}s", switchInfo.bundleName.c_str(), switchInfo.subName.c_str()); + InputMethodSysEvent::EventRecorder(IMEBehaviour::CHANGE_IME); if (!switchQueue_.IsReady(switchInfo)) { IMSA_HILOGD("start wait"); switchQueue_.Wait(switchInfo); @@ -379,6 +383,8 @@ int32_t InputMethodSystemAbility::OnSwitchInputMethod(const SwitchInfo &switchIn && !(switchInfo.bundleName == currentIme && BundleChecker::IsCurrentIme(IPCSkeleton::GetCallingTokenID(), currentIme))) { switchQueue_.Pop(); + InputMethodSysEvent::InputmethodFaultReporter( + ErrorCode::ERROR_STATUS_PERMISSION_DENIED, switchInfo.bundleName, "switch inputmethod failed!"); return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; } if (!IsNeedSwitch(switchInfo.bundleName, switchInfo.subName)) { @@ -393,6 +399,9 @@ int32_t InputMethodSystemAbility::OnSwitchInputMethod(const SwitchInfo &switchIn } ret = info.isNewIme ? Switch(switchInfo.bundleName, info) : SwitchExtension(info); switchQueue_.Pop(); + if (ret != ErrorCode::NO_ERROR) { + InputMethodSysEvent::InputmethodFaultReporter(ret, switchInfo.bundleName, "switch inputmethod failed!"); + } return ret; } @@ -559,7 +568,13 @@ int32_t InputMethodSystemAbility::OnUserStarted(const Message *msg) // user switch, reset currentImeInfo_ = nullptr ImeInfoInquirer::GetInstance().ResetCurrentImeInfo(); auto newIme = ImeInfoInquirer::GetInstance().GetStartedIme(userId_); - StartInputService(newIme); + InputMethodSysEvent::SetUserId(userId_); + if (!StartInputService(newIme)) { + IMSA_HILOGE("start input method failed"); + InputMethodSysEvent::InputmethodFaultReporter( + ErrorCode::ERROR_IME_START_FAILED, newIme, "user start ime failed!"); + return ErrorCode::ERROR_IME_START_FAILED; + } return ErrorCode::NO_ERROR; } diff --git a/services/src/peruser_session.cpp b/services/src/peruser_session.cpp index 68093021..93923e0e 100644 --- a/services/src/peruser_session.cpp +++ b/services/src/peruser_session.cpp @@ -631,6 +631,8 @@ bool PerUserSession::StartInputService(const std::string &imeName, bool isRetry) isImeStarted_.Clear(false); if (abms->StartAbility(want) != ErrorCode::NO_ERROR) { IMSA_HILOGE("failed to start ability"); + InputMethodSysEvent::InputmethodFaultReporter( + ErrorCode::ERROR_IME_START_FAILED, imeName, "StartInputService, failed to start ability."); } else if (isImeStarted_.GetValue()) { IMSA_HILOGI("ime started successfully"); return true;