Signed-off-by: ma-shaoyin <mashaoyin1@huawei.com>

Changes to be committed:
This commit is contained in:
ma-shaoyin 2023-07-12 11:12:21 +08:00
parent 0838d1ec4b
commit d741bc5524
7 changed files with 185 additions and 34 deletions

View File

@ -45,7 +45,10 @@ const std::unordered_map<std::string, EventType> EVENT_TYPE{ { "imeChange", IME_
InputMethodController::InputMethodController() : stop_(false) InputMethodController::InputMethodController() : stop_(false)
{ {
IMSA_HILOGI("InputMethodController structure"); IMSA_HILOGI("InputMethodController structure");
Initialize(); int32_t ret = Initialize();
if (ret != ErrorCode::NO_ERROR) {
InputMethodSysEvent::InputmethodFaultReporter(ret, "", "IMC initialize failed!");
}
} }
InputMethodController::~InputMethodController() InputMethodController::~InputMethodController()
@ -118,24 +121,24 @@ void InputMethodController::SetControllerListener(std::shared_ptr<ControllerList
} }
} }
bool InputMethodController::Initialize() int32_t InputMethodController::Initialize()
{ {
auto handler = new (std::nothrow) MessageHandler(); auto handler = new (std::nothrow) MessageHandler();
if (handler == nullptr) { if (handler == nullptr) {
IMSA_HILOGE("failed to new message handler"); IMSA_HILOGE("failed to new message handler");
return false; return ErrorCode::ERROR_NULL_POINTER;
} }
msgHandler_ = handler; msgHandler_ = handler;
auto client = new (std::nothrow) InputClientStub(); auto client = new (std::nothrow) InputClientStub();
if (client == nullptr) { if (client == nullptr) {
IMSA_HILOGE("failed to new client"); IMSA_HILOGE("failed to new client");
return false; return ErrorCode::ERROR_NULL_POINTER;
} }
client->SetHandler(msgHandler_); client->SetHandler(msgHandler_);
auto channel = new (std::nothrow) InputDataChannelStub(); auto channel = new (std::nothrow) InputDataChannelStub();
if (channel == nullptr) { if (channel == nullptr) {
IMSA_HILOGE("failed to new channel"); IMSA_HILOGE("failed to new channel");
return false; return ErrorCode::ERROR_NULL_POINTER;
} }
channel->SetHandler(msgHandler_); channel->SetHandler(msgHandler_);
InputAttribute attribute = { .inputPattern = InputAttribute::PATTERN_TEXT }; InputAttribute attribute = { .inputPattern = InputAttribute::PATTERN_TEXT };
@ -144,7 +147,7 @@ bool InputMethodController::Initialize()
// make AppExecFwk::EventHandler handler // make AppExecFwk::EventHandler handler
handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner()); handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
return true; return ErrorCode::NO_ERROR;
} }
sptr<IInputMethodSystemAbility> InputMethodController::GetSystemAbilityProxy() sptr<IInputMethodSystemAbility> InputMethodController::GetSystemAbilityProxy()

View File

@ -14,22 +14,22 @@
domain: INPUTMETHOD domain: INPUTMETHOD
SERVICE_INIT_FAILED: 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} 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} ERROR_CODE: {type: INT32, desc: Error code}
CREATE_COMPONENT_FAILED: INPUTMETHOD_UNAVAILABLE:
__BASE: {type: STATISTIC, level: CRITICAL, tag: IMCFailed, desc: Create component failed report} __BASE: {type: FAULT, level: CRITICAL, tag: IMEUnavaliable, desc: inputmethod unavailable}
USER_ID: {type: INT32, desc: The user id} 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} 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} __BASE: {type: STATISTIC, level: MINOR, tag: IMEUsage, desc: inputmethod using report}
USER_ID: {type: INT32, desc: the timer id} IME_START: {type: INT32, desc: the number of ime starts}
COMPONENT_ID: {type: INT32,desc: the component type} IME_CHANGE: {type: INT32, desc: the number of ime switchs}
ERROR_CODE: {type: INT32, desc: error code}
OPERATE_SOFTKEYBOARD: OPERATE_SOFTKEYBOARD:
__BASE: {type: BEHAVIOR, level: MINOR, tag: IMEOperate, desc: Operate the soft keyboard report} __BASE: {type: BEHAVIOR, level: MINOR, tag: IMEOperate, desc: Operate the soft keyboard report}

View File

@ -433,7 +433,7 @@ private:
InputMethodController(); InputMethodController();
~InputMethodController(); ~InputMethodController();
bool Initialize(); int32_t Initialize();
sptr<IInputMethodSystemAbility> GetSystemAbilityProxy(); sptr<IInputMethodSystemAbility> GetSystemAbilityProxy();
int32_t PrepareInput(InputClientInfo &inputClientInfo); int32_t PrepareInput(InputClientInfo &inputClientInfo);
int32_t StartInput(sptr<IInputClient> &client, bool isShowKeyboard, bool attachFlag); int32_t StartInput(sptr<IInputClient> &client, bool isShowKeyboard, bool attachFlag);

View File

@ -16,10 +16,13 @@
#ifndef INPUTMETHOD_SYSEVENT_H #ifndef INPUTMETHOD_SYSEVENT_H
#define INPUTMETHOD_SYSEVENT_H #define INPUTMETHOD_SYSEVENT_H
#include <map>
#include <mutex>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "global.h" #include "global.h"
#include "timer.h"
namespace OHOS { namespace OHOS {
namespace MiscServices { namespace MiscServices {
@ -35,19 +38,45 @@ enum OperateIMEInfoCode : int32_t {
IME_HIDE_SELF, IME_HIDE_SELF,
}; };
enum IMEBehaviour : int32_t {
START_IME = 0,
CHANGE_IME,
};
class InputMethodSysEvent { class InputMethodSysEvent {
public: public:
static void FaultReporter(int32_t userId, const std::string &bundleName, int32_t errCode); static void ServiceFaultReporter(const std::string &bundleName, int32_t errCode);
static void CreateComponentFailed(int32_t userId, int32_t errCode); static void InputmethodFaultReporter(int32_t errCode, const std::string &name, const std::string &info);
static void BehaviourReporter(const std::string &activeName, const std::string &inputMethodName); static void EventRecorder(IMEBehaviour behaciour);
static void OperateSoftkeyboardBehaviour(OperateIMEInfoCode infoCode); static void OperateSoftkeyboardBehaviour(OperateIMEInfoCode infoCode);
static void StartTimerForReport();
static void SetUserId(int32_t userId);
private: private:
using TimerCallback = std::function<void()>;
static void ImeUsageBehaviourReporter();
static const std::string GetOperateInfo(OperateIMEInfoCode infoCode); static const std::string GetOperateInfo(OperateIMEInfoCode infoCode);
static std::string GetOperateAction(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: private:
static const std::unordered_map<int32_t, std::string> operateInfo_; static const std::unordered_map<int32_t, std::string> operateInfo_;
static std::map<int32_t, int32_t> 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 MiscServices
} // namespace OHOS } // namespace OHOS

View File

@ -15,10 +15,11 @@
#include "inputmethod_sysevent.h" #include "inputmethod_sysevent.h"
#include "hisysevent.h"
#include <unistd.h> #include <unistd.h>
#include "common_timer_errors.h"
#include "hisysevent.h"
namespace OHOS { namespace OHOS {
namespace MiscServices { namespace MiscServices {
namespace { namespace {
@ -37,31 +38,60 @@ const std::unordered_map<int32_t, std::string> InputMethodSysEvent::operateInfo_
{IME_HIDE_SELF, "HideKeyboardSelf: hide soft keyboard self."} {IME_HIDE_SELF, "HideKeyboardSelf: hide soft keyboard self."}
}; };
void InputMethodSysEvent::FaultReporter(int32_t userId, const std::string &bundleName, int32_t errCode) std::map<int32_t, int32_t> 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", 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) { 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", int32_t ret = HiSysEventWrite(HiSysEventNameSpace::Domain::INPUTMETHOD, "INPUTMETHOD_UNAVAILABLE",
HiSysEventNameSpace::EventType::FAULT, "USER_ID", userId, "ERROR_CODE", errCode); HiSysEventNameSpace::EventType::FAULT, "USER_ID", userId_, "APP_NAME", name, "ERROR_CODE", errCode, "INFO",
info);
if (ret != HiviewDFX::SUCCESS) { 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", IMSA_HILOGE("msy ImeUsageBehaviourReporter");
HiSysEventNameSpace::EventType::BEHAVIOR, "ACTIVE_NAME", activeName, "INPUTMETHOD_NAME", inputMethodName); std::lock_guard<std::mutex> 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) { if (ret != HiviewDFX::SUCCESS) {
IMSA_HILOGE("hisysevent BehaviourReporter failed! ret %{public}d", ret); 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<std::mutex> lock(behaviourMutex_);
if (behaviour == IMEBehaviour::START_IME) {
inputmethodBehaviour_[START_IME]++;
} else if (behaviour == IMEBehaviour::CHANGE_IME) {
inputmethodBehaviour_[CHANGE_IME]++;
}
} }
void InputMethodSysEvent::OperateSoftkeyboardBehaviour(OperateIMEInfoCode infoCode) void InputMethodSysEvent::OperateSoftkeyboardBehaviour(OperateIMEInfoCode infoCode)
@ -104,5 +134,77 @@ std::string InputMethodSysEvent::GetOperateAction(OperateIMEInfoCode infoCode)
} }
return "unknow action."; 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<std::mutex> 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(&current, &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 MiscServices
} // namespace OHOS } // namespace OHOS

View File

@ -73,13 +73,16 @@ InputMethodSystemAbility::~InputMethodSystemAbility()
void InputMethodSystemAbility::OnStart() void InputMethodSystemAbility::OnStart()
{ {
IMSA_HILOGI("InputMethodSystemAbility::OnStart."); IMSA_HILOGI("InputMethodSystemAbility::OnStart.");
InputMethodSysEvent::StartTimerForReport();
if (state_ == ServiceRunningState::STATE_RUNNING) { if (state_ == ServiceRunningState::STATE_RUNNING) {
IMSA_HILOGI("ImsaService is already running."); IMSA_HILOGI("ImsaService is already running.");
return; return;
} }
Initialize(); Initialize();
InitServiceHandler(); InitServiceHandler();
if (Init() != ErrorCode::NO_ERROR) { int32_t ret = Init();
if (ret != ErrorCode::NO_ERROR) {
InputMethodSysEvent::ServiceFaultReporter("imf", ret);
auto callback = [=]() { Init(); }; auto callback = [=]() { Init(); };
serviceHandler_->PostTask(callback, INIT_INTERVAL); serviceHandler_->PostTask(callback, INIT_INTERVAL);
IMSA_HILOGE("Init failed. Try again 10s later"); IMSA_HILOGE("Init failed. Try again 10s later");
@ -138,6 +141,7 @@ int32_t InputMethodSystemAbility::Init()
return OsAccountManager::QueryActiveOsAccountIds(userIds) == ERR_OK && !userIds.empty(); return OsAccountManager::QueryActiveOsAccountIds(userIds) == ERR_OK && !userIds.empty();
})) { })) {
userId_ = userIds[0]; userId_ = userIds[0];
InputMethodSysEvent::SetUserId(userId_);
userSession_->UpdateCurrentUserId(userId_); userSession_->UpdateCurrentUserId(userId_);
} }
StartUserIdListener(); StartUserIdListener();
@ -289,7 +293,6 @@ int32_t InputMethodSystemAbility::SetCoreAndAgent(sptr<IInputMethodCore> core, s
return ErrorCode::ERROR_NOT_CURRENT_IME; return ErrorCode::ERROR_NOT_CURRENT_IME;
} }
if (core == nullptr || agent == nullptr) { if (core == nullptr || agent == nullptr) {
InputMethodSysEvent::CreateComponentFailed(userId_, ErrorCode::ERROR_NULL_POINTER);
IMSA_HILOGE("InputMethodSystemAbility::core or agent is nullptr"); IMSA_HILOGE("InputMethodSystemAbility::core or agent is nullptr");
return ErrorCode::ERROR_NULL_POINTER; 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) 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()); 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)) { if (!switchQueue_.IsReady(switchInfo)) {
IMSA_HILOGD("start wait"); IMSA_HILOGD("start wait");
switchQueue_.Wait(switchInfo); switchQueue_.Wait(switchInfo);
@ -379,6 +383,8 @@ int32_t InputMethodSystemAbility::OnSwitchInputMethod(const SwitchInfo &switchIn
&& !(switchInfo.bundleName == currentIme && !(switchInfo.bundleName == currentIme
&& BundleChecker::IsCurrentIme(IPCSkeleton::GetCallingTokenID(), currentIme))) { && BundleChecker::IsCurrentIme(IPCSkeleton::GetCallingTokenID(), currentIme))) {
switchQueue_.Pop(); switchQueue_.Pop();
InputMethodSysEvent::InputmethodFaultReporter(
ErrorCode::ERROR_STATUS_PERMISSION_DENIED, switchInfo.bundleName, "switch inputmethod failed!");
return ErrorCode::ERROR_STATUS_PERMISSION_DENIED; return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
} }
if (!IsNeedSwitch(switchInfo.bundleName, switchInfo.subName)) { 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); ret = info.isNewIme ? Switch(switchInfo.bundleName, info) : SwitchExtension(info);
switchQueue_.Pop(); switchQueue_.Pop();
if (ret != ErrorCode::NO_ERROR) {
InputMethodSysEvent::InputmethodFaultReporter(ret, switchInfo.bundleName, "switch inputmethod failed!");
}
return ret; return ret;
} }
@ -559,7 +568,13 @@ int32_t InputMethodSystemAbility::OnUserStarted(const Message *msg)
// user switch, reset currentImeInfo_ = nullptr // user switch, reset currentImeInfo_ = nullptr
ImeInfoInquirer::GetInstance().ResetCurrentImeInfo(); ImeInfoInquirer::GetInstance().ResetCurrentImeInfo();
auto newIme = ImeInfoInquirer::GetInstance().GetStartedIme(userId_); 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; return ErrorCode::NO_ERROR;
} }

View File

@ -631,6 +631,8 @@ bool PerUserSession::StartInputService(const std::string &imeName, bool isRetry)
isImeStarted_.Clear(false); isImeStarted_.Clear(false);
if (abms->StartAbility(want) != ErrorCode::NO_ERROR) { if (abms->StartAbility(want) != ErrorCode::NO_ERROR) {
IMSA_HILOGE("failed to start ability"); IMSA_HILOGE("failed to start ability");
InputMethodSysEvent::InputmethodFaultReporter(
ErrorCode::ERROR_IME_START_FAILED, imeName, "StartInputService, failed to start ability.");
} else if (isImeStarted_.GetValue()) { } else if (isImeStarted_.GetValue()) {
IMSA_HILOGI("ime started successfully"); IMSA_HILOGI("ime started successfully");
return true; return true;