1 /*
2 * Copyright (c) 2022-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "inputmethod_sysevent.h"
17
18 #include <unistd.h>
19
20 #include "common_timer_errors.h"
21 #include "hisysevent.h"
22
23 namespace OHOS {
24 namespace MiscServices {
25 namespace {
26 using HiSysEventNameSpace = OHOS::HiviewDFX::HiSysEvent;
27 } // namespace
28
29 const std::unordered_map<int32_t, std::string> InputMethodSysEvent::operateInfo_ = {
30 { static_cast<int32_t>(OperateIMEInfoCode::IME_SHOW_ATTACH), "Attach: attach, bind and show soft keyboard." },
31 { static_cast<int32_t>(OperateIMEInfoCode::IME_SHOW_ENEDITABLE), "ShowTextInput: enter editable state, show soft "
32 "keyboard." },
33 { static_cast<int32_t>(OperateIMEInfoCode::IME_SHOW_NORMAL), "ShowSoftKeyboard: show soft keyboard." },
34 { static_cast<int32_t>(OperateIMEInfoCode::IME_UNBIND), "Close: unbind." },
35 { static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_UNBIND), "Close: hide soft keyboard, and unbind." },
36 { static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_UNEDITABLE), "HideTextInput: hide soft keyboard, quit "
37 "editable state." },
38 { static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_NORMAL), "HideSoftKeyboard, hide soft keyboard." },
39 { static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_UNFOCUSED), "OnUnfocused: unfocused, hide soft keyboard." },
40 { static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_SELF), "HideKeyboardSelf: hide soft keyboard self." }
41 };
42
43 std::map<int32_t, int32_t> InputMethodSysEvent::inputmethodBehaviour_ = {
44 {static_cast<int32_t>(IMEBehaviour::START_IME), 0},
45 {static_cast<int32_t>(IMEBehaviour::CHANGE_IME), 0}
46 };
47
~InputMethodSysEvent()48 InputMethodSysEvent::~InputMethodSysEvent()
49 {
50 StopTimer();
51 }
52
GetInstance()53 InputMethodSysEvent &InputMethodSysEvent::GetInstance()
54 {
55 static InputMethodSysEvent instance;
56 return instance;
57 }
58
ServiceFaultReporter(const std::string & componentName,int32_t errCode)59 void InputMethodSysEvent::ServiceFaultReporter(const std::string &componentName, int32_t errCode)
60 {
61 IMSA_HILOGD("start.");
62 int32_t ret = HiSysEventWrite(HiSysEventNameSpace::Domain::INPUTMETHOD, "SERVICE_INIT_FAILED",
63 HiSysEventNameSpace::EventType::FAULT, "USER_ID", userId_, "COMPONENT_ID", componentName, "ERROR_CODE",
64 errCode);
65 if (ret != HiviewDFX::SUCCESS) {
66 IMSA_HILOGE("hisysevent ServiceFaultReporter failed! ret: %{public}d, errCode: %{public}d", ret, errCode);
67 }
68 }
69
InputmethodFaultReporter(int32_t errCode,const std::string & name,const std::string & info)70 void InputMethodSysEvent::InputmethodFaultReporter(int32_t errCode, const std::string &name, const std::string &info)
71 {
72 IMSA_HILOGD("start.");
73 int32_t ret = HiSysEventWrite(HiSysEventNameSpace::Domain::INPUTMETHOD, "UNAVAILABLE_INPUTMETHOD",
74 HiSysEventNameSpace::EventType::FAULT, "USER_ID", userId_, "APP_NAME", name, "ERROR_CODE", errCode, "INFO",
75 info);
76 if (ret != HiviewDFX::SUCCESS) {
77 IMSA_HILOGE("hisysevent InputmethodFaultReporter failed! ret: %{public}d,errCode %{public}d", ret, errCode);
78 }
79 }
80
ImeUsageBehaviourReporter()81 void InputMethodSysEvent::ImeUsageBehaviourReporter()
82 {
83 IMSA_HILOGD("start.");
84 int ret = HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::INPUTMETHOD, "IME_USAGE",
85 HiSysEventNameSpace::EventType::STATISTIC, "IME_START",
86 inputmethodBehaviour_[static_cast<int32_t>(IMEBehaviour::START_IME)], "IME_CHANGE",
87 inputmethodBehaviour_[static_cast<int32_t>(IMEBehaviour::CHANGE_IME)]);
88 if (ret != HiviewDFX::SUCCESS) {
89 IMSA_HILOGE("hisysevent BehaviourReporter failed! ret: %{public}d", ret);
90 }
91 {
92 std::lock_guard<std::mutex> lock(behaviourMutex_);
93 inputmethodBehaviour_[static_cast<int32_t>(IMEBehaviour::START_IME)] = 0;
94 inputmethodBehaviour_[static_cast<int32_t>(IMEBehaviour::CHANGE_IME)] = 0;
95 }
96 StartTimerForReport();
97 }
98
RecordEvent(IMEBehaviour behaviour)99 void InputMethodSysEvent::RecordEvent(IMEBehaviour behaviour)
100 {
101 IMSA_HILOGD("run in.");
102 std::lock_guard<std::mutex> lock(behaviourMutex_);
103 if (behaviour == IMEBehaviour::START_IME) {
104 ++inputmethodBehaviour_[static_cast<int32_t>(IMEBehaviour::START_IME)];
105 } else if (behaviour == IMEBehaviour::CHANGE_IME) {
106 ++inputmethodBehaviour_[static_cast<int32_t>(IMEBehaviour::CHANGE_IME)];
107 }
108 }
109
OperateSoftkeyboardBehaviour(OperateIMEInfoCode infoCode)110 void InputMethodSysEvent::OperateSoftkeyboardBehaviour(OperateIMEInfoCode infoCode)
111 {
112 IMSA_HILOGD("run in.");
113 int32_t ret = HiSysEventWrite(HiSysEventNameSpace::Domain::INPUTMETHOD, "OPERATE_SOFTKEYBOARD",
114 HiSysEventNameSpace::EventType::BEHAVIOR, "OPERATING", GetOperateAction(static_cast<int32_t>(infoCode)),
115 "OPERATE_INFO", GetOperateInfo(static_cast<int32_t>(infoCode)));
116 if (ret != HiviewDFX::SUCCESS) {
117 IMSA_HILOGE("Hisysevent: operate soft keyboard report failed! ret: %{public}d", ret);
118 }
119 }
120
ReportImeState(ImeState state,pid_t pid,const std::string & bundleName)121 void InputMethodSysEvent::ReportImeState(ImeState state, pid_t pid, const std::string &bundleName)
122 {
123 IMSA_HILOGD("run in.");
124 int32_t ret = HiSysEventWrite(HiSysEventNameSpace::Domain::INPUTMETHOD, "IME_STATE_CHANGED",
125 HiSysEventNameSpace::EventType::BEHAVIOR, "STATE", static_cast<int32_t>(state), "PID", pid, "BUNDLE_NAME",
126 bundleName);
127 if (ret != HiviewDFX::SUCCESS) {
128 IMSA_HILOGE("ime: %{public}s state: %{public}d report failed! ret: %{public}d", bundleName.c_str(),
129 static_cast<int32_t>(state), ret);
130 }
131 }
132
GetOperateInfo(int32_t infoCode)133 const std::string InputMethodSysEvent::GetOperateInfo(int32_t infoCode)
134 {
135 auto iter = operateInfo_.find(static_cast<int32_t>(infoCode));
136 if (iter != operateInfo_.end()) {
137 return iter->second;
138 }
139 return "unknow operating.";
140 }
141
GetOperateAction(int32_t infoCode)142 std::string InputMethodSysEvent::GetOperateAction(int32_t infoCode)
143 {
144 switch (infoCode) {
145 case static_cast<int32_t>(OperateIMEInfoCode::IME_SHOW_ATTACH):
146 case static_cast<int32_t>(OperateIMEInfoCode::IME_SHOW_ENEDITABLE):
147 case static_cast<int32_t>(OperateIMEInfoCode::IME_SHOW_NORMAL):
148 return "show";
149 case static_cast<int32_t>(OperateIMEInfoCode::IME_UNBIND):
150 return "unbind";
151 case static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_UNBIND):
152 return "hide and unbind";
153 case static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_UNEDITABLE):
154 case static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_NORMAL):
155 case static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_UNFOCUSED):
156 case static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_SELF):
157 return "hide";
158 default:
159 break;
160 }
161 return "unknow action.";
162 }
163
SetUserId(int32_t userId)164 void InputMethodSysEvent::SetUserId(int32_t userId)
165 {
166 userId_ = userId;
167 }
168
StopTimer()169 void InputMethodSysEvent::StopTimer()
170 {
171 IMSA_HILOGD("start.");
172 std::lock_guard<std::mutex> lock(timerLock_);
173 if (timer_ == nullptr) {
174 IMSA_HILOGE("timer_ is nullptr.");
175 return;
176 }
177 timer_->Unregister(timerId_);
178 timer_->Shutdown();
179 }
180
StartTimer(const TimerCallback & callback,uint32_t interval)181 bool InputMethodSysEvent::StartTimer(const TimerCallback &callback, uint32_t interval)
182 {
183 IMSA_HILOGD("start.");
184 if (timer_ == nullptr) {
185 timer_ = std::make_shared<Utils::Timer>("OS_imfTimer");
186 uint32_t ret = timer_->Setup();
187 if (ret != Utils::TIMER_ERR_OK) {
188 IMSA_HILOGE("create Timer error.");
189 return false;
190 }
191 timerId_ = timer_->Register(callback, interval, true);
192 } else {
193 IMSA_HILOGD("timer_ is not nullptr, Update timer.");
194 timer_->Unregister(timerId_);
195 timerId_ = timer_->Register(callback, interval, false);
196 }
197 return true;
198 }
199
StartTimerForReport()200 bool InputMethodSysEvent::StartTimerForReport()
201 {
202 IMSA_HILOGD("start.");
203 auto reportCallback = [this]() { ImeUsageBehaviourReporter(); };
204 std::lock_guard<std::mutex> lock(timerLock_);
205 return StartTimer(reportCallback, ONE_DAY_IN_HOURS * ONE_HOUR_IN_SECONDS * SECONDS_TO_MILLISECONDS);
206 }
207 } // namespace MiscServices
208 } // namespace OHOS