• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 std::chrono::steady_clock::time_point InputMethodSysEvent::lastReportTime_ = std::chrono::steady_clock::now();
30 const std::unordered_map<int32_t, std::string> InputMethodSysEvent::operateInfo_ = {
31     { static_cast<int32_t>(OperateIMEInfoCode::IME_SHOW_ATTACH), "Attach: attach, bind and show soft keyboard." },
32     { static_cast<int32_t>(OperateIMEInfoCode::IME_SHOW_ENEDITABLE), "ShowTextInput: enter editable state, show soft "
33                                                                      "keyboard." },
34     { static_cast<int32_t>(OperateIMEInfoCode::IME_SHOW_NORMAL), "ShowSoftKeyboard: show soft keyboard." },
35     { static_cast<int32_t>(OperateIMEInfoCode::IME_UNBIND), "Close: unbind." },
36     { static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_UNBIND), "Close: hide soft keyboard, and unbind." },
37     { static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_UNEDITABLE), "HideTextInput: hide soft keyboard, quit "
38                                                                      "editable state." },
39     { static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_NORMAL), "HideSoftKeyboard, hide soft keyboard." },
40     { static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_UNFOCUSED), "OnUnfocused: unfocused, hide soft keyboard." },
41     { static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_SELF), "HideKeyboardSelf: hide soft keyboard self." }
42 };
43 
44 std::map<int32_t, int32_t> InputMethodSysEvent::inputmethodBehaviour_ = {
45     { static_cast<int32_t>(IMEBehaviour::START_IME), 0 }, { 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     auto currentTime = std::chrono::steady_clock::now();
114     if (static_cast<uint32_t>(
115             std::chrono::duration_cast<std::chrono::minutes>(currentTime - lastReportTime_).count()) <
116         REPORT_INTERVAL) {
117         IMSA_HILOGD("Event triggered within 10 minutes, skipping report.");
118         return;
119     }
120     int32_t ret = HiSysEventWrite(HiSysEventNameSpace::Domain::INPUTMETHOD, "OPERATE_SOFTKEYBOARD",
121         HiSysEventNameSpace::EventType::BEHAVIOR, "OPERATING", GetOperateAction(static_cast<int32_t>(infoCode)),
122         "OPERATE_INFO", GetOperateInfo(static_cast<int32_t>(infoCode)));
123     if (ret != HiviewDFX::SUCCESS) {
124         IMSA_HILOGE("Hisysevent: operate soft keyboard report failed! ret: %{public}d", ret);
125     }
126     lastReportTime_ = currentTime;
127     IMSA_HILOGD("Event triggered before 10 minutes, report successfully.");
128 }
129 
ReportImeState(ImeState state,pid_t pid,const std::string & bundleName)130 void InputMethodSysEvent::ReportImeState(ImeState state, pid_t pid, const std::string &bundleName)
131 {
132     IMSA_HILOGD("run in.");
133     auto currentTime = std::chrono::steady_clock::now();
134     if (static_cast<uint32_t>(
135             std::chrono::duration_cast<std::chrono::minutes>(currentTime - lastReportTime_).count()) <
136         REPORT_INTERVAL) {
137         IMSA_HILOGD("Event triggered within 10 minutes, skipping report.");
138         return;
139     }
140 
141     int32_t ret = HiSysEventWrite(HiSysEventNameSpace::Domain::INPUTMETHOD, "IME_STATE_CHANGED",
142         HiSysEventNameSpace::EventType::BEHAVIOR, "STATE", static_cast<int32_t>(state), "PID", pid, "BUNDLE_NAME",
143         bundleName);
144     if (ret != HiviewDFX::SUCCESS) {
145         IMSA_HILOGE("ime: %{public}s state: %{public}d report failed! ret: %{public}d", bundleName.c_str(),
146             static_cast<int32_t>(state), ret);
147     }
148     lastReportTime_ = currentTime;
149     IMSA_HILOGD("Event triggered before 10 minutes, report successfully.");
150 }
151 
GetOperateInfo(int32_t infoCode)152 const std::string InputMethodSysEvent::GetOperateInfo(int32_t infoCode)
153 {
154     auto iter = operateInfo_.find(static_cast<int32_t>(infoCode));
155     if (iter != operateInfo_.end()) {
156         return iter->second;
157     }
158     return "unknow operating.";
159 }
160 
GetOperateAction(int32_t infoCode)161 std::string InputMethodSysEvent::GetOperateAction(int32_t infoCode)
162 {
163     switch (infoCode) {
164         case static_cast<int32_t>(OperateIMEInfoCode::IME_SHOW_ATTACH):
165         case static_cast<int32_t>(OperateIMEInfoCode::IME_SHOW_ENEDITABLE):
166         case static_cast<int32_t>(OperateIMEInfoCode::IME_SHOW_NORMAL):
167             return "show";
168         case static_cast<int32_t>(OperateIMEInfoCode::IME_UNBIND):
169             return "unbind";
170         case static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_UNBIND):
171             return "hide and unbind";
172         case static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_UNEDITABLE):
173         case static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_NORMAL):
174         case static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_UNFOCUSED):
175         case static_cast<int32_t>(OperateIMEInfoCode::IME_HIDE_SELF):
176             return "hide";
177         default:
178             break;
179     }
180     return "unknow action.";
181 }
182 
SetUserId(int32_t userId)183 void InputMethodSysEvent::SetUserId(int32_t userId)
184 {
185     userId_ = userId;
186 }
187 
StopTimer()188 void InputMethodSysEvent::StopTimer()
189 {
190     IMSA_HILOGD("start.");
191     std::lock_guard<std::mutex> lock(timerLock_);
192     if (timer_ == nullptr) {
193         IMSA_HILOGE("timer_ is nullptr.");
194         return;
195     }
196     timer_->Unregister(timerId_);
197     timer_->Shutdown();
198 }
199 
StartTimer(const TimerCallback & callback,uint32_t interval)200 bool InputMethodSysEvent::StartTimer(const TimerCallback &callback, uint32_t interval)
201 {
202     IMSA_HILOGD("start.");
203     if (timer_ == nullptr) {
204         timer_ = std::make_shared<Utils::Timer>("OS_imfTimer");
205         uint32_t ret = timer_->Setup();
206         if (ret != Utils::TIMER_ERR_OK) {
207             IMSA_HILOGE("create Timer error.");
208             return false;
209         }
210         timerId_ = timer_->Register(callback, interval, true);
211     } else {
212         IMSA_HILOGD("timer_ is not nullptr, Update timer.");
213         timer_->Unregister(timerId_);
214         timerId_ = timer_->Register(callback, interval, false);
215     }
216     return true;
217 }
218 
StartTimerForReport()219 bool InputMethodSysEvent::StartTimerForReport()
220 {
221     IMSA_HILOGD("start.");
222     auto reportCallback = [this]() { ImeUsageBehaviourReporter(); };
223     std::lock_guard<std::mutex> lock(timerLock_);
224     return StartTimer(reportCallback, ONE_DAY_IN_HOURS * ONE_HOUR_IN_SECONDS * SECONDS_TO_MILLISECONDS);
225 }
226 
ReportSystemShortCut(const std::string & shortcutName)227 void InputMethodSysEvent::ReportSystemShortCut(const std::string &shortcutName)
228 {
229     IMSA_HILOGD("run in.");
230     int32_t ret = HiSysEventWrite(HiSysEventNameSpace::Domain::INPUTMETHOD_UE, "SYSTEM_SHORTCUT",
231         HiSysEventNameSpace::EventType::BEHAVIOR, "PROCESS_NAME", "inputmethod_service", "SHORTCUT_NAME", shortcutName);
232     if (ret != HiviewDFX::SUCCESS) {
233         IMSA_HILOGE("system shortcut: %{public}s report failed! ret: %{public}d", shortcutName.c_str(), ret);
234     }
235 }
236 } // namespace MiscServices
237 } // namespace OHOS