1 /*
2 * Copyright (C) 2021 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 "input_method_system_ability.h"
17
18 #include <unistd.h>
19
20 #include "ability_manager_client.h"
21 #include "application_info.h"
22 #include "combination_key.h"
23 #include "common_event_support.h"
24 #include "errors.h"
25 #include "global.h"
26 #include "im_common_event_manager.h"
27 #include "ime_aging_manager.h"
28 #include "ime_cfg_manager.h"
29 #include "ime_info_inquirer.h"
30 #include "input_method_utils.h"
31 #include "input_type_manager.h"
32 #include "ipc_skeleton.h"
33 #include "iservice_registry.h"
34 #include "itypes_util.h"
35 #include "key_event.h"
36 #include "message_handler.h"
37 #include "native_token_info.h"
38 #include "os_account_manager.h"
39 #include "scene_board_judgement.h"
40 #include "sys/prctl.h"
41 #include "system_ability_definition.h"
42 #include "system_language_observer.h"
43 #include "wms_connection_observer.h"
44
45 namespace OHOS {
46 namespace MiscServices {
47 using namespace MessageID;
48 using namespace AccountSA;
49 REGISTER_SYSTEM_ABILITY_BY_ID(InputMethodSystemAbility, INPUT_METHOD_SYSTEM_ABILITY_ID, true);
50 constexpr std::int32_t INIT_INTERVAL = 10000L;
51 constexpr std::int32_t MAIN_USER_ID = 100;
52 constexpr uint32_t RETRY_INTERVAL = 100;
53 constexpr uint32_t BLOCK_RETRY_TIMES = 100;
54 constexpr uint32_t SWITCH_BLOCK_TIME = 150000;
55 static const std::string PERMISSION_CONNECT_IME_ABILITY = "ohos.permission.CONNECT_IME_ABILITY";
56 std::shared_ptr<AppExecFwk::EventHandler> InputMethodSystemAbility::serviceHandler_;
57
InputMethodSystemAbility(int32_t systemAbilityId,bool runOnCreate)58 InputMethodSystemAbility::InputMethodSystemAbility(int32_t systemAbilityId, bool runOnCreate)
59 : SystemAbility(systemAbilityId, runOnCreate), state_(ServiceRunningState::STATE_NOT_START)
60 {
61 }
62
InputMethodSystemAbility()63 InputMethodSystemAbility::InputMethodSystemAbility() : state_(ServiceRunningState::STATE_NOT_START)
64 {
65 }
66
~InputMethodSystemAbility()67 InputMethodSystemAbility::~InputMethodSystemAbility()
68 {
69 stop_ = true;
70 Message *msg = new Message(MessageID::MSG_ID_QUIT_WORKER_THREAD, nullptr);
71 MessageHandler::Instance()->SendMessage(msg);
72 if (workThreadHandler.joinable()) {
73 workThreadHandler.join();
74 }
75 }
76
OnStart()77 void InputMethodSystemAbility::OnStart()
78 {
79 IMSA_HILOGI("InputMethodSystemAbility::OnStart.");
80 if (!InputMethodSysEvent::GetInstance().StartTimerForReport()) {
81 IMSA_HILOGE("Start sysevent timer failed!");
82 }
83 if (state_ == ServiceRunningState::STATE_RUNNING) {
84 IMSA_HILOGI("ImsaService is already running.");
85 return;
86 }
87 Initialize();
88 InitServiceHandler();
89 int32_t ret = Init();
90 if (ret != ErrorCode::NO_ERROR) {
91 InputMethodSysEvent::GetInstance().ServiceFaultReporter("imf", ret);
92 auto callback = [=]() { Init(); };
93 serviceHandler_->PostTask(callback, INIT_INTERVAL);
94 IMSA_HILOGE("Init failed. Try again 10s later");
95 }
96 InitHiTrace();
97 InputMethodSyncTrace tracer("InputMethodController Attach trace.");
98 InputmethodDump::GetInstance().AddDumpAllMethod(
99 std::bind(&InputMethodSystemAbility::DumpAllMethod, this, std::placeholders::_1));
100 IMSA_HILOGI("Start ImsaService ErrorCode::NO_ERROR.");
101 return;
102 }
103
Dump(int fd,const std::vector<std::u16string> & args)104 int InputMethodSystemAbility::Dump(int fd, const std::vector<std::u16string> &args)
105 {
106 IMSA_HILOGD("InputMethodSystemAbility::Dump");
107 std::vector<std::string> argsStr;
108 for (auto item : args) {
109 argsStr.emplace_back(Str16ToStr8(item));
110 }
111 InputmethodDump::GetInstance().Dump(fd, argsStr);
112 return ERR_OK;
113 }
114
DumpAllMethod(int fd)115 void InputMethodSystemAbility::DumpAllMethod(int fd)
116 {
117 IMSA_HILOGD("InputMethodSystemAbility::DumpAllMethod");
118 std::vector<int32_t> ids;
119 int errCode = OsAccountManager::QueryActiveOsAccountIds(ids);
120 if (errCode != ERR_OK) {
121 dprintf(fd, "\n - InputMethodSystemAbility::DumpAllMethod get Active Id failed.\n");
122 return;
123 }
124 dprintf(fd, "\n - DumpAllMethod get Active Id succeed,count=%zu,", ids.size());
125 for (auto id : ids) {
126 const auto ¶ms = ImeInfoInquirer::GetInstance().GetDumpInfo(id);
127 if (params.empty()) {
128 IMSA_HILOGD("userId: %{public}d The IME properties is empty.", id);
129 dprintf(fd, "\n - The IME properties about the Active Id %d is empty.\n", id);
130 continue;
131 }
132 dprintf(fd, "\n - The Active Id:%d get input method:\n%s\n", id, params.c_str());
133 }
134 IMSA_HILOGD("InputMethodSystemAbility::DumpAllMethod end.");
135 }
136
Init()137 int32_t InputMethodSystemAbility::Init()
138 {
139 bool isSuccess = Publish(this);
140 if (!isSuccess) {
141 return -1;
142 }
143 state_ = ServiceRunningState::STATE_RUNNING;
144 ImeCfgManager::GetInstance().Init();
145 ImeInfoInquirer::GetInstance().InitConfig();
146 InitMonitors();
147 return ErrorCode::NO_ERROR;
148 }
149
SetCurrentUserId()150 void InputMethodSystemAbility::SetCurrentUserId()
151 {
152 std::vector<int32_t> userIds;
153 if (!BlockRetry(RETRY_INTERVAL, BLOCK_RETRY_TIMES, [&userIds]() -> bool {
154 return OsAccountManager::QueryActiveOsAccountIds(userIds) == ERR_OK && !userIds.empty();
155 })) {
156 IMSA_HILOGE("get userId failed");
157 return;
158 }
159 IMSA_HILOGD("get userId success :%{public}d", userIds[0]);
160 userId_ = userIds[0];
161 InputMethodSysEvent::GetInstance().SetUserId(userId_);
162 userSession_->UpdateCurrentUserId(userId_);
163 }
164
OnStop()165 void InputMethodSystemAbility::OnStop()
166 {
167 IMSA_HILOGI("OnStop started.");
168 serviceHandler_ = nullptr;
169 state_ = ServiceRunningState::STATE_NOT_START;
170 }
171
InitServiceHandler()172 void InputMethodSystemAbility::InitServiceHandler()
173 {
174 IMSA_HILOGI("InitServiceHandler started.");
175 if (serviceHandler_ != nullptr) {
176 IMSA_HILOGE("InputMethodSystemAbility, already init.");
177 return;
178 }
179 std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create("OS_InputMethodSystemAbility");
180 serviceHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
181
182 IMSA_HILOGI("InitServiceHandler succeeded.");
183 }
184
185 /**
186 * Initialization of Input method management service
187 * \n It's called after the service starts, before any transaction.
188 */
Initialize()189 void InputMethodSystemAbility::Initialize()
190 {
191 IMSA_HILOGI("InputMethodSystemAbility::Initialize");
192 // init work thread to handle the messages
193 workThreadHandler = std::thread([this] { WorkThread(); });
194 identityChecker_ = std::make_shared<IdentityCheckerImpl>();
195 userId_ = MAIN_USER_ID;
196 userSession_ = std::make_shared<PerUserSession>(userId_);
197 InputMethodSysEvent::GetInstance().SetUserId(userId_);
198 }
199
StartUserIdListener()200 void InputMethodSystemAbility::StartUserIdListener()
201 {
202 sptr<ImCommonEventManager> imCommonEventManager = ImCommonEventManager::GetInstance();
203 bool isSuccess = imCommonEventManager->SubscribeEvent(EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED);
204 if (isSuccess) {
205 IMSA_HILOGI("Initialize subscribe service event success");
206 return;
207 }
208
209 IMSA_HILOGE("failed. Try again 10s later");
210 auto callback = [this]() { StartUserIdListener(); };
211 serviceHandler_->PostTask(callback, INIT_INTERVAL);
212 }
213
StartInputService(const std::shared_ptr<ImeNativeCfg> & imeId)214 bool InputMethodSystemAbility::StartInputService(const std::shared_ptr<ImeNativeCfg> &imeId)
215 {
216 return userSession_->StartInputService(imeId, true);
217 }
218
StopInputService()219 void InputMethodSystemAbility::StopInputService()
220 {
221 userSession_->StopCurrentIme();
222 }
223
PrepareInput(InputClientInfo & clientInfo)224 int32_t InputMethodSystemAbility::PrepareInput(InputClientInfo &clientInfo)
225 {
226 auto ret = GenerateClientInfo(clientInfo);
227 if (ret != ErrorCode::NO_ERROR) {
228 return ret;
229 }
230 return userSession_->OnPrepareInput(clientInfo);
231 }
232
GenerateClientInfo(InputClientInfo & clientInfo)233 int32_t InputMethodSystemAbility::GenerateClientInfo(InputClientInfo &clientInfo)
234 {
235 if (clientInfo.client == nullptr || clientInfo.channel == nullptr) {
236 return ErrorCode::ERROR_NULL_POINTER;
237 }
238 auto deathRecipient = new (std::nothrow) InputDeathRecipient();
239 if (deathRecipient == nullptr) {
240 IMSA_HILOGE("failed to new deathRecipient");
241 return ErrorCode::ERROR_EX_NULL_POINTER;
242 }
243 clientInfo.pid = IPCSkeleton::GetCallingPid();
244 clientInfo.uid = IPCSkeleton::GetCallingUid();
245 clientInfo.userID = userId_;
246 clientInfo.deathRecipient = deathRecipient;
247 return ErrorCode::NO_ERROR;
248 }
249
ReleaseInput(sptr<IInputClient> client)250 int32_t InputMethodSystemAbility::ReleaseInput(sptr<IInputClient> client)
251 {
252 if (client == nullptr) {
253 IMSA_HILOGE("InputMethodSystemAbility::client is nullptr");
254 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
255 }
256 return userSession_->OnReleaseInput(client);
257 };
258
StartInput(InputClientInfo & inputClientInfo,sptr<IRemoteObject> & agent)259 int32_t InputMethodSystemAbility::StartInput(InputClientInfo &inputClientInfo, sptr<IRemoteObject> &agent)
260 {
261 if (userSession_->GetCurrentClientPid() != IPCSkeleton::GetCallingPid()) {
262 //进程变化时需要通知inputstart
263 inputClientInfo.isNotifyInputStart = true;
264 }
265 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
266 if (!identityChecker_->IsBroker(tokenId)) {
267 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId)) {
268 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
269 }
270 }
271
272 if (!userSession_->IsProxyImeEnable()) {
273 CheckSecurityMode(inputClientInfo);
274 }
275 int32_t ret = PrepareInput(inputClientInfo);
276 if (ret != ErrorCode::NO_ERROR) {
277 IMSA_HILOGE("PrepareInput failed");
278 return ret;
279 }
280 return userSession_->OnStartInput(inputClientInfo, agent);
281 };
282
CheckSecurityMode(InputClientInfo & inputClientInfo)283 void InputMethodSystemAbility::CheckSecurityMode(InputClientInfo &inputClientInfo)
284 {
285 if (inputClientInfo.config.inputAttribute.GetSecurityFlag()) {
286 if (InputTypeManager::GetInstance().IsStarted()) {
287 IMSA_HILOGD("security ime has started.");
288 return;
289 }
290 auto ret = StartInputType(InputType::SECURITY_INPUT);
291 IMSA_HILOGD("switch to security ime ret = %{public}d.", ret);
292 return;
293 }
294 if (!InputTypeManager::GetInstance().IsStarted() || InputTypeManager::GetInstance().IsCameraImeStarted()) {
295 IMSA_HILOGD("security ime is not start or camera ime started, keep current.");
296 return;
297 }
298 auto ret = StartInputType(InputType::NONE);
299 IMSA_HILOGD("Exit security ime ret = %{public}d.", ret);
300 }
301
ShowInput(sptr<IInputClient> client)302 int32_t InputMethodSystemAbility::ShowInput(sptr<IInputClient> client)
303 {
304 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
305 if (!identityChecker_->IsBroker(tokenId)) {
306 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, userSession_->GetCurrentClientPid())) {
307 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
308 }
309 }
310 if (client == nullptr) {
311 IMSA_HILOGE("IMSA, client is nullptr");
312 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
313 }
314 return userSession_->OnShowInput(client);
315 }
316
HideInput(sptr<IInputClient> client)317 int32_t InputMethodSystemAbility::HideInput(sptr<IInputClient> client)
318 {
319 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
320 if (!identityChecker_->IsBroker(tokenId)) {
321 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, userSession_->GetCurrentClientPid())) {
322 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
323 }
324 }
325 if (client == nullptr) {
326 IMSA_HILOGE("IMSA, client is nullptr");
327 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
328 }
329 return userSession_->OnHideInput(client);
330 };
331
StopInputSession()332 int32_t InputMethodSystemAbility::StopInputSession()
333 {
334 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
335 if (!identityChecker_->IsBroker(tokenId)) {
336 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, userSession_->GetCurrentClientPid())) {
337 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
338 }
339 }
340 return userSession_->OnHideCurrentInput();
341 }
342
RequestShowInput()343 int32_t InputMethodSystemAbility::RequestShowInput()
344 {
345 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
346 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId)
347 && !identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
348 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
349 }
350 return userSession_->OnRequestShowInput();
351 }
352
RequestHideInput()353 int32_t InputMethodSystemAbility::RequestHideInput()
354 {
355 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
356 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId)
357 && !identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
358 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
359 }
360 return userSession_->OnRequestHideInput();
361 }
362
SetCoreAndAgent(const sptr<IInputMethodCore> & core,const sptr<IInputMethodAgent> & agent)363 int32_t InputMethodSystemAbility::SetCoreAndAgent(
364 const sptr<IInputMethodCore> &core, const sptr<IInputMethodAgent> &agent)
365 {
366 IMSA_HILOGD("InputMethodSystemAbility run in");
367 if (IsCurrentIme()) {
368 return userSession_->OnSetCoreAndAgent(core, agent);
369 }
370 if (identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
371 return userSession_->OnRegisterProxyIme(core, agent);
372 }
373 return ErrorCode::ERROR_NOT_CURRENT_IME;
374 }
375
HideCurrentInput()376 int32_t InputMethodSystemAbility::HideCurrentInput()
377 {
378 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
379 if (identityChecker_->IsBroker(tokenId)) {
380 return userSession_->OnHideCurrentInput();
381 }
382 if (!identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
383 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
384 }
385 return userSession_->OnHideCurrentInput();
386 };
387
ShowCurrentInput()388 int32_t InputMethodSystemAbility::ShowCurrentInput()
389 {
390 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
391 if (identityChecker_->IsBroker(tokenId)) {
392 return userSession_->OnShowCurrentInput();
393 }
394
395 if (!identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
396 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
397 }
398 return userSession_->OnShowCurrentInput();
399 };
400
PanelStatusChange(const InputWindowStatus & status,const InputWindowInfo & windowInfo)401 int32_t InputMethodSystemAbility::PanelStatusChange(const InputWindowStatus &status, const InputWindowInfo &windowInfo)
402 {
403 auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
404 if (!identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), currentImeCfg->bundleName)) {
405 IMSA_HILOGE("not current ime");
406 return ErrorCode::ERROR_NOT_CURRENT_IME;
407 }
408 return userSession_->OnPanelStatusChange(status, windowInfo);
409 }
410
UpdateListenEventFlag(InputClientInfo & clientInfo,EventType eventType)411 int32_t InputMethodSystemAbility::UpdateListenEventFlag(InputClientInfo &clientInfo, EventType eventType)
412 {
413 IMSA_HILOGI("eventType: %{public}u, eventFlag: %{public}u", eventType, clientInfo.eventFlag);
414 if ((eventType == IME_SHOW || eventType == IME_HIDE)
415 && !identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) {
416 IMSA_HILOGE("not system application");
417 return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
418 }
419 auto ret = GenerateClientInfo(clientInfo);
420 if (ret != ErrorCode::NO_ERROR) {
421 return ret;
422 }
423 return userSession_->OnUpdateListenEventFlag(clientInfo);
424 }
425
IsCurrentIme()426 bool InputMethodSystemAbility::IsCurrentIme()
427 {
428 if (InputTypeManager::GetInstance().IsStarted()) {
429 auto currentTypeIme = InputTypeManager::GetInstance().GetCurrentIme();
430 return identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), currentTypeIme.bundleName);
431 }
432 auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
433 return identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), currentImeCfg->bundleName);
434 }
435
IsInputTypeSupported(InputType type)436 bool InputMethodSystemAbility::IsInputTypeSupported(InputType type)
437 {
438 return InputTypeManager::GetInstance().IsSupported(type);
439 }
440
StartInputType(InputType type)441 int32_t InputMethodSystemAbility::StartInputType(InputType type)
442 {
443 if (type != InputType::NONE) {
444 ImeIdentification ime;
445 int32_t ret = InputTypeManager::GetInstance().GetImeByInputType(type, ime);
446 if (ret != ErrorCode::NO_ERROR) {
447 return ret;
448 }
449 SwitchInfo switchInfo = { std::chrono::system_clock::now(), ime.bundleName, ime.subName };
450 switchQueue_.Push(switchInfo);
451 IMSA_HILOGI("start input type: %{public}d", type);
452 return type == InputType::SECURITY_INPUT ? OnStartInputType(switchInfo, false)
453 : OnStartInputType(switchInfo, true);
454 }
455 auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
456 SwitchInfo switchInfo = { std::chrono::system_clock::now(), cfgIme->bundleName, cfgIme->subName };
457 switchQueue_.Push(switchInfo);
458 return OnStartInputType(switchInfo, false);
459 }
460
ExitCurrentInputType()461 int32_t InputMethodSystemAbility::ExitCurrentInputType()
462 {
463 auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultImeInfo(userId_);
464 if (defaultIme == nullptr) {
465 IMSA_HILOGE("failed to get default ime");
466 return ErrorCode::ERROR_PERSIST_CONFIG;
467 }
468 if (!identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), defaultIme->prop.name)) {
469 return ErrorCode::ERROR_NOT_DEFAULT_IME;
470 }
471 if (userSession_->CheckSecurityMode()) {
472 return StartInputType(InputType::SECURITY_INPUT);
473 }
474 return userSession_->ExitCurrentInputType();
475 }
476
IsPanelShown(const PanelInfo & panelInfo,bool & isShown)477 int32_t InputMethodSystemAbility::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
478 {
479 if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) {
480 IMSA_HILOGE("not system application");
481 return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
482 }
483 return userSession_->IsPanelShown(panelInfo, isShown);
484 }
485
DisplayOptionalInputMethod()486 int32_t InputMethodSystemAbility::DisplayOptionalInputMethod()
487 {
488 IMSA_HILOGD("InputMethodSystemAbility run in");
489 return OnDisplayOptionalInputMethod();
490 }
491
SwitchInputMethod(const std::string & bundleName,const std::string & subName,SwitchTrigger trigger)492 int32_t InputMethodSystemAbility::SwitchInputMethod(
493 const std::string &bundleName, const std::string &subName, SwitchTrigger trigger)
494 {
495 // IMSA not check permission, add this verify for prevent counterfeit
496 if (trigger == SwitchTrigger::IMSA) {
497 IMSA_HILOGW("caller counterfeit!");
498 return ErrorCode::ERROR_BAD_PARAMETERS;
499 }
500 SwitchInfo switchInfo = { std::chrono::system_clock::now(), bundleName, subName };
501 if (enableImeOn_ && !EnableImeDataParser::GetInstance()->CheckNeedSwitch(switchInfo, userId_)) {
502 IMSA_HILOGW("Enable mode off or switch is not enable, stoped!");
503 return ErrorCode::ERROR_ENABLE_IME;
504 }
505 switchInfo.timestamp = std::chrono::system_clock::now();
506 switchQueue_.Push(switchInfo);
507 return InputTypeManager::GetInstance().IsInputType({ bundleName, subName })
508 ? OnStartInputType(switchInfo, true)
509 : OnSwitchInputMethod(switchInfo, trigger);
510 }
511
OnSwitchInputMethod(const SwitchInfo & switchInfo,SwitchTrigger trigger)512 int32_t InputMethodSystemAbility::OnSwitchInputMethod(const SwitchInfo &switchInfo, SwitchTrigger trigger)
513 {
514 IMSA_HILOGD("run in, switchInfo: %{public}s|%{public}s", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
515 InputMethodSysEvent::GetInstance().RecordEvent(IMEBehaviour::CHANGE_IME);
516 if (!switchQueue_.IsReady(switchInfo)) {
517 IMSA_HILOGD("start wait");
518 switchQueue_.Wait(switchInfo);
519 }
520 IMSA_HILOGI("start switch %{public}s|%{public}s", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
521 int32_t ret = CheckSwitchPermission(switchInfo, trigger);
522 if (ret != ErrorCode::NO_ERROR) {
523 InputMethodSysEvent::GetInstance().InputmethodFaultReporter(
524 ErrorCode::ERROR_STATUS_PERMISSION_DENIED, switchInfo.bundleName, "switch inputmethod failed!");
525 switchQueue_.Pop();
526 return ret;
527 }
528
529 if (!InputTypeManager::GetInstance().IsStarted() && !IsNeedSwitch(switchInfo.bundleName, switchInfo.subName)) {
530 switchQueue_.Pop();
531 return ErrorCode::NO_ERROR;
532 }
533 auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, switchInfo.bundleName, switchInfo.subName);
534 if (info == nullptr) {
535 switchQueue_.Pop();
536 return ErrorCode::ERROR_BAD_PARAMETERS;
537 }
538 ret = info->isNewIme ? Switch(switchInfo.bundleName, info) : SwitchExtension(info);
539 if (InputTypeManager::GetInstance().IsStarted()) {
540 InputTypeManager::GetInstance().Set(false);
541 }
542 switchQueue_.Pop();
543 if (ret != ErrorCode::NO_ERROR) {
544 InputMethodSysEvent::GetInstance().InputmethodFaultReporter(
545 ret, switchInfo.bundleName, "switch inputmethod failed!");
546 }
547 return ret;
548 }
549
OnStartInputType(const SwitchInfo & switchInfo,bool isCheckPermission)550 int32_t InputMethodSystemAbility::OnStartInputType(const SwitchInfo &switchInfo, bool isCheckPermission)
551 {
552 if (!switchQueue_.IsReady(switchInfo)) {
553 IMSA_HILOGD("start wait");
554 switchQueue_.Wait(switchInfo);
555 usleep(SWITCH_BLOCK_TIME);
556 }
557 auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
558 if (switchInfo.bundleName == cfgIme->bundleName && switchInfo.subName == cfgIme->subName) {
559 IMSA_HILOGD("start input type is current ime, exit input type.");
560 int32_t ret = userSession_->ExitCurrentInputType();
561 switchQueue_.Pop();
562 return ret;
563 }
564 IMSA_HILOGD("start switch %{public}s|%{public}s", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
565 if (isCheckPermission && !IsStartInputTypePermitted()) {
566 IMSA_HILOGE("not permitted to start input type");
567 switchQueue_.Pop();
568 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
569 }
570 if (!IsNeedSwitch(switchInfo.bundleName, switchInfo.subName)) {
571 IMSA_HILOGI("no need to switch");
572 switchQueue_.Pop();
573 return ErrorCode::NO_ERROR;
574 }
575 int32_t ret = SwitchInputType(switchInfo);
576 switchQueue_.Pop();
577 return ret;
578 }
579
IsNeedSwitch(const std::string & bundleName,const std::string & subName)580 bool InputMethodSystemAbility::IsNeedSwitch(const std::string &bundleName, const std::string &subName)
581 {
582 if (InputTypeManager::GetInstance().IsStarted()) {
583 ImeIdentification target = { bundleName, subName };
584 return !(target == InputTypeManager::GetInstance().GetCurrentIme());
585 }
586 auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
587 IMSA_HILOGI("currentIme: %{public}s/%{public}s, targetIme: %{public}s/%{public}s",
588 currentImeCfg->bundleName.c_str(), currentImeCfg->subName.c_str(), bundleName.c_str(), subName.c_str());
589 if ((subName.empty() && bundleName == currentImeCfg->bundleName)
590 || (!subName.empty() && subName == currentImeCfg->subName && currentImeCfg->bundleName == bundleName)) {
591 IMSA_HILOGI("no need to switch");
592 return false;
593 }
594 return true;
595 }
596
Switch(const std::string & bundleName,const std::shared_ptr<ImeInfo> & info)597 int32_t InputMethodSystemAbility::Switch(const std::string &bundleName, const std::shared_ptr<ImeInfo> &info)
598 {
599 auto currentImeBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
600 return bundleName != currentImeBundleName ? SwitchExtension(info) : SwitchSubType(info);
601 }
602
603 // Switch the current InputMethodExtension to the new InputMethodExtension
SwitchExtension(const std::shared_ptr<ImeInfo> & info)604 int32_t InputMethodSystemAbility::SwitchExtension(const std::shared_ptr<ImeInfo> &info)
605 {
606 StopInputService();
607 std::string targetImeName = info->prop.name + "/" + info->prop.id;
608 ImeCfgManager::GetInstance().ModifyImeCfg({ userId_, targetImeName, info->subProp.id });
609 ImeInfoInquirer::GetInstance().SetCurrentImeInfo(info);
610 ImeNativeCfg targetIme = { targetImeName, info->prop.name, info->subProp.id, info->prop.id };
611 if (!StartInputService(std::make_shared<ImeNativeCfg>(targetIme))) {
612 IMSA_HILOGE("start input method failed");
613 return ErrorCode::ERROR_IME_START_FAILED;
614 }
615 userSession_->NotifyImeChangeToClients(info->prop, info->subProp);
616 return ErrorCode::NO_ERROR;
617 }
618
619 // Inform current InputMethodExtension to switch subtype
SwitchSubType(const std::shared_ptr<ImeInfo> & info)620 int32_t InputMethodSystemAbility::SwitchSubType(const std::shared_ptr<ImeInfo> &info)
621 {
622 auto ret = userSession_->SwitchSubtype(info->subProp);
623 if (ret != ErrorCode::NO_ERROR) {
624 IMSA_HILOGE("failed to inform ime to switch subtype, ret: %{public}d", ret);
625 return ret;
626 }
627 auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->imeId;
628 ImeCfgManager::GetInstance().ModifyImeCfg({ userId_, currentIme, info->subProp.id });
629 ImeInfoInquirer::GetInstance().SetCurrentImeInfo(info);
630 userSession_->NotifyImeChangeToClients(info->prop, info->subProp);
631 return ErrorCode::NO_ERROR;
632 }
633
SwitchInputType(const SwitchInfo & switchInfo)634 int32_t InputMethodSystemAbility::SwitchInputType(const SwitchInfo &switchInfo)
635 {
636 auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
637 bool checkSameIme = InputTypeManager::GetInstance().IsStarted()
638 ? switchInfo.bundleName == InputTypeManager::GetInstance().GetCurrentIme().bundleName
639 : switchInfo.bundleName == currentIme->bundleName;
640 if (checkSameIme) {
641 IMSA_HILOGD("only need to switch subtype: %{public}s", switchInfo.subName.c_str());
642 auto ret = userSession_->SwitchSubtype({ .name = switchInfo.bundleName, .id = switchInfo.subName });
643 if (ret == ErrorCode::NO_ERROR) {
644 InputTypeManager::GetInstance().Set(true, { switchInfo.bundleName, switchInfo.subName });
645 }
646 return ret;
647 }
648 IMSA_HILOGD("need to switch ime: %{public}s|%{public}s", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
649 auto targetImeProperty = ImeInfoInquirer::GetInstance().GetImeByBundleName(userId_, switchInfo.bundleName);
650 if (targetImeProperty == nullptr) {
651 return ErrorCode::ERROR_NULL_POINTER;
652 }
653
654 StopInputService();
655 std::string targetName = switchInfo.bundleName + "/" + targetImeProperty->id;
656 ImeNativeCfg targetIme = { targetName, switchInfo.bundleName, switchInfo.subName, targetImeProperty->id };
657 InputTypeManager::GetInstance().Set(true, { switchInfo.bundleName, switchInfo.subName });
658 if (!StartInputService(std::make_shared<ImeNativeCfg>(targetIme))) {
659 IMSA_HILOGE("start input method failed");
660 InputTypeManager::GetInstance().Set(false);
661 return ErrorCode::ERROR_IME_START_FAILED;
662 }
663 int32_t ret = userSession_->SwitchSubtype({ .name = switchInfo.bundleName, .id = switchInfo.subName });
664 if (ret != ErrorCode::NO_ERROR) {
665 InputTypeManager::GetInstance().Set(false);
666 return ret;
667 }
668 return ErrorCode::NO_ERROR;
669 }
670
671 // Deprecated because of no permission check, kept for compatibility
HideCurrentInputDeprecated()672 int32_t InputMethodSystemAbility::HideCurrentInputDeprecated()
673 {
674 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
675 if (!identityChecker_->IsBroker(tokenId)) {
676 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, userSession_->GetCurrentClientPid())) {
677 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
678 }
679 }
680 return userSession_->OnHideCurrentInput();
681 };
682
ShowCurrentInputDeprecated()683 int32_t InputMethodSystemAbility::ShowCurrentInputDeprecated()
684 {
685 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
686 if (!identityChecker_->IsBroker(tokenId)) {
687 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, userSession_->GetCurrentClientPid())) {
688 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
689 }
690 }
691 return userSession_->OnShowCurrentInput();
692 };
693
GetCurrentInputMethod()694 std::shared_ptr<Property> InputMethodSystemAbility::GetCurrentInputMethod()
695 {
696 return ImeInfoInquirer::GetInstance().GetCurrentInputMethod(userId_);
697 }
698
GetCurrentInputMethodSubtype()699 std::shared_ptr<SubProperty> InputMethodSystemAbility::GetCurrentInputMethodSubtype()
700 {
701 return ImeInfoInquirer::GetInstance().GetCurrentSubtype(userId_);
702 }
703
GetDefaultInputMethod(std::shared_ptr<Property> & prop)704 int32_t InputMethodSystemAbility::GetDefaultInputMethod(std::shared_ptr<Property> &prop)
705 {
706 return ImeInfoInquirer::GetInstance().GetDefaultInputMethod(userId_, prop);
707 }
708
GetInputMethodConfig(OHOS::AppExecFwk::ElementName & inputMethodConfig)709 int32_t InputMethodSystemAbility::GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig)
710 {
711 return ImeInfoInquirer::GetInstance().GetInputMethodConfig(userId_, inputMethodConfig);
712 }
713
ListInputMethod(InputMethodStatus status,std::vector<Property> & props)714 int32_t InputMethodSystemAbility::ListInputMethod(InputMethodStatus status, std::vector<Property> &props)
715 {
716 return ImeInfoInquirer::GetInstance().ListInputMethod(userId_, status, props, enableImeOn_);
717 }
718
ListCurrentInputMethodSubtype(std::vector<SubProperty> & subProps)719 int32_t InputMethodSystemAbility::ListCurrentInputMethodSubtype(std::vector<SubProperty> &subProps)
720 {
721 return ImeInfoInquirer::GetInstance().ListCurrentInputMethodSubtype(userId_, subProps);
722 }
723
ListInputMethodSubtype(const std::string & bundleName,std::vector<SubProperty> & subProps)724 int32_t InputMethodSystemAbility::ListInputMethodSubtype(
725 const std::string &bundleName, std::vector<SubProperty> &subProps)
726 {
727 return ImeInfoInquirer::GetInstance().ListInputMethodSubtype(userId_, bundleName, subProps);
728 }
729
730 /**
731 * Work Thread of input method management service
732 * \n Remote commands which may change the state or data in the service will be handled sequentially in this thread.
733 */
WorkThread()734 void InputMethodSystemAbility::WorkThread()
735 {
736 prctl(PR_SET_NAME, "OS_IMSAWorkThread");
737 while (!stop_) {
738 Message *msg = MessageHandler::Instance()->GetMessage();
739 switch (msg->msgId_) {
740 case MSG_ID_USER_START: {
741 OnUserStarted(msg);
742 break;
743 }
744 case MSG_ID_USER_REMOVED: {
745 OnUserRemoved(msg);
746 break;
747 }
748 case MSG_ID_PACKAGE_REMOVED: {
749 OnPackageRemoved(msg);
750 break;
751 }
752 case MSG_ID_HIDE_KEYBOARD_SELF: {
753 userSession_->OnHideSoftKeyBoardSelf();
754 break;
755 }
756 default: {
757 IMSA_HILOGD("the message is %{public}d.", msg->msgId_);
758 break;
759 }
760 }
761 delete msg;
762 }
763 }
764
765 /**
766 * Called when a user is started. (EVENT_USER_STARTED is received)
767 * \n Run in work thread of input method management service
768 * \param msg the parameters are saved in msg->msgContent_
769 * \return ErrorCode
770 */
OnUserStarted(const Message * msg)771 int32_t InputMethodSystemAbility::OnUserStarted(const Message *msg)
772 {
773 if (msg->msgContent_ == nullptr) {
774 IMSA_HILOGE("msgContent is nullptr.");
775 return ErrorCode::ERROR_NULL_POINTER;
776 }
777 int32_t oldUserId = userId_;
778 userId_ = msg->msgContent_->ReadInt32();
779 if (oldUserId == userId_) {
780 IMSA_HILOGI("device boot, userId: %{public}d", userId_);
781 return ErrorCode::NO_ERROR;
782 }
783 IMSA_HILOGI("%{public}d switch to %{public}d.", oldUserId, userId_);
784 userSession_->UpdateCurrentUserId(userId_);
785 InputMethodSysEvent::GetInstance().SetUserId(userId_);
786 if (enableImeOn_) {
787 EnableImeDataParser::GetInstance()->OnUserChanged(userId_);
788 }
789 if (enableSecurityMode_) {
790 SecurityModeParser::GetInstance()->GetFullModeList(userId_);
791 }
792 userSession_->StopCurrentIme();
793 ImeAgingManager::GetInstance().Clear();
794 // user switch, reset currentImeInfo_ = nullptr
795 ImeInfoInquirer::GetInstance().SetCurrentImeInfo(nullptr);
796
797 if (!userSession_->IsWmsReady()) {
798 IMSA_HILOGI("wms not ready, wait");
799 return ErrorCode::NO_ERROR;
800 }
801 if (!userSession_->StartCurrentIme(userId_, true)) {
802 IMSA_HILOGE("start input method failed");
803 return ErrorCode::ERROR_IME_START_FAILED;
804 }
805 return ErrorCode::NO_ERROR;
806 }
807
OnUserRemoved(const Message * msg)808 int32_t InputMethodSystemAbility::OnUserRemoved(const Message *msg)
809 {
810 if (msg->msgContent_ == nullptr) {
811 IMSA_HILOGE("Aborted! Message is nullptr.");
812 return ErrorCode::ERROR_NULL_POINTER;
813 }
814 auto userId = msg->msgContent_->ReadInt32();
815 IMSA_HILOGI("Start: %{public}d", userId);
816 ImeCfgManager::GetInstance().DeleteImeCfg(userId);
817 return ErrorCode::NO_ERROR;
818 }
819
820 /**
821 * Called when a package is removed.
822 * \n Run in work thread of input method management service
823 * \param msg the parameters are saved in msg->msgContent_
824 * \return ErrorCode::NO_ERROR
825 * \return ErrorCode::ERROR_USER_NOT_UNLOCKED user not unlocked
826 * \return ErrorCode::ERROR_BAD_PARAMETERS bad parameter
827 */
OnPackageRemoved(const Message * msg)828 int32_t InputMethodSystemAbility::OnPackageRemoved(const Message *msg)
829 {
830 MessageParcel *data = msg->msgContent_;
831 if (data == nullptr) {
832 IMSA_HILOGD("data is nullptr");
833 return ErrorCode::ERROR_NULL_POINTER;
834 }
835 int32_t userId = 0;
836 std::string packageName;
837 if (!ITypesUtil::Unmarshal(*data, userId, packageName)) {
838 IMSA_HILOGE("Failed to read message parcel");
839 return ErrorCode::ERROR_EX_PARCELABLE;
840 }
841 // 用户移除也会有该通知,如果移除的app用户不是当前用户,则不处理
842 if (userId != userId_) {
843 IMSA_HILOGD("userId: %{public}d, currentUserId: %{public}d,", userId, userId_);
844 return ErrorCode::NO_ERROR;
845 }
846 auto currentImeBundle = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName;
847 if (packageName == currentImeBundle) {
848 // Switch to the default ime
849 IMSA_HILOGI("user[%{public}d] ime: %{public}s is uninstalled", userId, packageName.c_str());
850 auto info = ImeInfoInquirer::GetInstance().GetDefaultImeInfo(userId);
851 if (info == nullptr) {
852 return ErrorCode::ERROR_PERSIST_CONFIG;
853 }
854 int32_t ret = SwitchExtension(info);
855 IMSA_HILOGI("switch ret = %{public}d", ret);
856 }
857 return ErrorCode::NO_ERROR;
858 }
859
OnDisplayOptionalInputMethod()860 int32_t InputMethodSystemAbility::OnDisplayOptionalInputMethod()
861 {
862 IMSA_HILOGD("InputMethodSystemAbility::OnDisplayOptionalInputMethod");
863 AAFwk::Want want;
864 want.SetAction(SELECT_DIALOG_ACTION);
865 want.SetElementName(SELECT_DIALOG_HAP, SELECT_DIALOG_ABILITY);
866 int32_t ret = AAFwk::AbilityManagerClient::GetInstance()->StartAbility(want);
867 if (ret != ErrorCode::NO_ERROR && ret != START_SERVICE_ABILITY_ACTIVATING) {
868 IMSA_HILOGE("Start InputMethod ability failed, err = %{public}d", ret);
869 return ErrorCode::ERROR_EX_SERVICE_SPECIFIC;
870 }
871 IMSA_HILOGI("Start InputMethod ability success.");
872 return ErrorCode::NO_ERROR;
873 }
874
SwitchByCombinationKey(uint32_t state)875 int32_t InputMethodSystemAbility::SwitchByCombinationKey(uint32_t state)
876 {
877 IMSA_HILOGD("InputMethodSystemAbility::SwitchByCombinationKey");
878 if (userSession_->IsProxyImeEnable()) {
879 IMSA_HILOGI("proxy enable, not switch");
880 return ErrorCode::NO_ERROR;
881 }
882 if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_MODE, state)) {
883 IMSA_HILOGI("switch mode");
884 return SwitchMode();
885 }
886 if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_LANGUAGE, state)) {
887 IMSA_HILOGI("switch language");
888 return SwitchLanguage();
889 }
890 if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_IME, state)) {
891 IMSA_HILOGI("switch ime");
892 return SwitchType();
893 }
894 IMSA_HILOGE("keycode undefined");
895 return ErrorCode::ERROR_EX_UNSUPPORTED_OPERATION;
896 }
897
SwitchMode()898 int32_t InputMethodSystemAbility::SwitchMode()
899 {
900 auto bundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
901 auto subName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->subName;
902 auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, bundleName, subName);
903 if (info == nullptr) {
904 IMSA_HILOGE("current ime is abnormal");
905 return ErrorCode::ERROR_BAD_PARAMETERS;
906 }
907 if (info->isNewIme) {
908 IMSA_HILOGD("the switching operation is handed over to ime");
909 return ErrorCode::NO_ERROR;
910 }
911 auto condition = info->subProp.mode == "upper" ? Condition::LOWER : Condition::UPPER;
912 auto target = ImeInfoInquirer::GetInstance().FindTargetSubtypeByCondition(info->subProps, condition);
913 if (target == nullptr) {
914 IMSA_HILOGE("target is empty");
915 return ErrorCode::ERROR_BAD_PARAMETERS;
916 }
917 SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id };
918 switchQueue_.Push(switchInfo);
919 return OnSwitchInputMethod(switchInfo, SwitchTrigger::IMSA);
920 }
921
SwitchLanguage()922 int32_t InputMethodSystemAbility::SwitchLanguage()
923 {
924 auto bundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
925 auto subName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->subName;
926 auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, bundleName, subName);
927 if (info == nullptr) {
928 IMSA_HILOGE("current ime is abnormal");
929 return ErrorCode::ERROR_BAD_PARAMETERS;
930 }
931 if (info->isNewIme) {
932 IMSA_HILOGD("the switching operation is handed over to ime");
933 return ErrorCode::NO_ERROR;
934 }
935 if (info->subProp.language != "chinese" && info->subProp.language != "english") {
936 return ErrorCode::NO_ERROR;
937 }
938 auto condition = info->subProp.language == "chinese" ? Condition::ENGLISH : Condition::CHINESE;
939 auto target = ImeInfoInquirer::GetInstance().FindTargetSubtypeByCondition(info->subProps, condition);
940 if (target == nullptr) {
941 IMSA_HILOGE("target is empty");
942 return ErrorCode::ERROR_BAD_PARAMETERS;
943 }
944 SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id };
945 switchQueue_.Push(switchInfo);
946 return OnSwitchInputMethod(switchInfo, SwitchTrigger::IMSA);
947 }
948
SwitchType()949 int32_t InputMethodSystemAbility::SwitchType()
950 {
951 SwitchInfo switchInfo = { std::chrono::system_clock::now(), "", "" };
952 int32_t ret = ImeInfoInquirer::GetInstance().GetNextSwitchInfo(switchInfo, userId_, enableImeOn_);
953 if (ret != ErrorCode::NO_ERROR) {
954 IMSA_HILOGE("Get next SwitchInfo failed, stop switching ime.");
955 return ret;
956 }
957 IMSA_HILOGD("switch to: %{public}s", switchInfo.bundleName.c_str());
958 switchInfo.timestamp = std::chrono::system_clock::now();
959 switchQueue_.Push(switchInfo);
960 return OnSwitchInputMethod(switchInfo, SwitchTrigger::IMSA);
961 }
962
InitMonitors()963 void InputMethodSystemAbility::InitMonitors()
964 {
965 int32_t ret = InitAccountMonitor();
966 IMSA_HILOGI("init account monitor, ret: %{public}d", ret);
967 StartUserIdListener();
968 ret = InitKeyEventMonitor();
969 IMSA_HILOGI("init KeyEvent monitor, ret: %{public}d", ret);
970 ret = InitWmsMonitor();
971 IMSA_HILOGI("init wms monitor, ret: %{public}d", ret);
972 InitSystemLanguageMonitor();
973 if (ImeInfoInquirer::GetInstance().IsEnableInputMethod()) {
974 IMSA_HILOGW("Enter enable mode");
975 EnableImeDataParser::GetInstance()->Initialize(userId_);
976 enableImeOn_ = true;
977 RegisterEnableImeObserver();
978 }
979 if (ImeInfoInquirer::GetInstance().IsEnableSecurityMode()) {
980 IMSA_HILOGW("Enter security mode");
981 enableSecurityMode_ = true;
982 RegisterSecurityModeObserver();
983 }
984 }
985
InitAccountMonitor()986 int32_t InputMethodSystemAbility::InitAccountMonitor()
987 {
988 IMSA_HILOGI("InputMethodSystemAbility::InitAccountMonitor");
989 return ImCommonEventManager::GetInstance()->SubscribeAccountManagerService([this]() { SetCurrentUserId(); });
990 }
991
InitKeyEventMonitor()992 int32_t InputMethodSystemAbility::InitKeyEventMonitor()
993 {
994 IMSA_HILOGI("InputMethodSystemAbility::InitKeyEventMonitor");
995 bool ret = ImCommonEventManager::GetInstance()->SubscribeKeyboardEvent(
996 [this](uint32_t keyCode) { return SwitchByCombinationKey(keyCode); });
997 return ret ? ErrorCode::NO_ERROR : ErrorCode::ERROR_SERVICE_START_FAILED;
998 }
999
InitWmsMonitor()1000 bool InputMethodSystemAbility::InitWmsMonitor()
1001 {
1002 return ImCommonEventManager::GetInstance()->SubscribeWindowManagerService(
1003 [this](bool isOnFocused, int32_t pid, int32_t uid) {
1004 return isOnFocused ? userSession_->OnFocused(pid, uid) : userSession_->OnUnfocused(pid, uid);
1005 },
1006 [this]() {
1007 if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
1008 IMSA_HILOGI("scb enable, register WMS connection listener");
1009 InitWmsConnectionMonitor();
1010 return;
1011 }
1012 IMSA_HILOGI("scb disable, start ime");
1013 SetCurrentUserId();
1014 userSession_->StartCurrentIme(userId_, true);
1015 });
1016 }
1017
InitWmsConnectionMonitor()1018 void InputMethodSystemAbility::InitWmsConnectionMonitor()
1019 {
1020 WmsConnectionMonitorManager::GetInstance().RegisterWMSConnectionChangedListener(
1021 [this](int32_t userId, int32_t screenId) {
1022 SetCurrentUserId();
1023 IMSA_HILOGI("WMS connect, start ime, userId: %{public}d, currentUserId: %{public}d", userId, userId_);
1024 if (userId != userId_) {
1025 return;
1026 }
1027 userSession_->StartCurrentIme(userId_, true);
1028 });
1029 }
1030
InitSystemLanguageMonitor()1031 void InputMethodSystemAbility::InitSystemLanguageMonitor()
1032 {
1033 SystemLanguageObserver::GetInstance().Watch(
1034 [this]() { ImeInfoInquirer::GetInstance().RefreshCurrentImeInfo(userId_); });
1035 }
1036
RegisterEnableImeObserver()1037 void InputMethodSystemAbility::RegisterEnableImeObserver()
1038 {
1039 int32_t ret = SettingsDataUtils::GetInstance()->CreateAndRegisterObserver(
1040 EnableImeDataParser::ENABLE_IME, [this]() { DatashareCallback(EnableImeDataParser::ENABLE_IME); });
1041 IMSA_HILOGI("Register enable ime observer, ret: %{public}d", ret);
1042 ret = SettingsDataUtils::GetInstance()->CreateAndRegisterObserver(
1043 EnableImeDataParser::ENABLE_KEYBOARD, [this]() { DatashareCallback(EnableImeDataParser::ENABLE_KEYBOARD); });
1044 IMSA_HILOGI("Register enable keyboard observer, ret: %{public}d", ret);
1045 }
1046
RegisterSecurityModeObserver()1047 void InputMethodSystemAbility::RegisterSecurityModeObserver()
1048 {
1049 int32_t ret = SettingsDataUtils::GetInstance()->CreateAndRegisterObserver(
1050 SecurityModeParser::SECURITY_MODE, [this]() { DatashareCallback(SecurityModeParser::SECURITY_MODE); });
1051 IMSA_HILOGI("Register security mode observer, ret: %{public}d", ret);
1052 }
1053
DatashareCallback(const std::string & key)1054 void InputMethodSystemAbility::DatashareCallback(const std::string &key)
1055 {
1056 IMSA_HILOGI("run in.");
1057 if (key == EnableImeDataParser::ENABLE_KEYBOARD || key == EnableImeDataParser::ENABLE_IME) {
1058 std::lock_guard<std::mutex> autoLock(checkMutex_);
1059 SwitchInfo switchInfo;
1060 if (EnableImeDataParser::GetInstance()->CheckNeedSwitch(key, switchInfo, userId_)) {
1061 switchInfo.timestamp = std::chrono::system_clock::now();
1062 switchQueue_.Push(switchInfo);
1063 OnSwitchInputMethod(switchInfo, SwitchTrigger::IMSA);
1064 }
1065 }
1066
1067 if (key == SecurityModeParser::SECURITY_MODE) {
1068 auto currentBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
1069 if (SecurityModeParser::GetInstance()->IsSecurityChange(currentBundleName, userId_)) {
1070 int32_t security;
1071 SecurityModeParser::GetInstance()->GetSecurityMode(currentBundleName, security, userId_);
1072 userSession_->OnSecurityChange(security);
1073 }
1074 }
1075 }
1076
GetSecurityMode(int32_t & security)1077 int32_t InputMethodSystemAbility::GetSecurityMode(int32_t &security)
1078 {
1079 IMSA_HILOGD("GetSecurityMode");
1080 if (!enableSecurityMode_) {
1081 security = static_cast<int32_t>(SecurityMode::FULL);
1082 return ErrorCode::NO_ERROR;
1083 }
1084 auto callBundleName = identityChecker_->GetBundleNameByToken(IPCSkeleton::GetCallingTokenID());
1085 return SecurityModeParser::GetInstance()->GetSecurityMode(callBundleName, security, userId_);
1086 }
1087
UnRegisteredProxyIme(UnRegisteredType type,const sptr<IInputMethodCore> & core)1088 int32_t InputMethodSystemAbility::UnRegisteredProxyIme(UnRegisteredType type, const sptr<IInputMethodCore> &core)
1089 {
1090 if (!identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
1091 IMSA_HILOGE("not native sa");
1092 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1093 }
1094 return userSession_->OnUnRegisteredProxyIme(type, core);
1095 }
1096
CheckSwitchPermission(const SwitchInfo & switchInfo,SwitchTrigger trigger)1097 int32_t InputMethodSystemAbility::CheckSwitchPermission(const SwitchInfo &switchInfo, SwitchTrigger trigger)
1098 {
1099 IMSA_HILOGD("trigger: %{public}d", static_cast<int32_t>(trigger));
1100 if (trigger == SwitchTrigger::IMSA) {
1101 return ErrorCode::NO_ERROR;
1102 }
1103 if (trigger == SwitchTrigger::SYSTEM_APP) {
1104 if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) {
1105 IMSA_HILOGE("not system app");
1106 return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
1107 }
1108 if (!identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)) {
1109 IMSA_HILOGE("not have PERMISSION_CONNECT_IME_ABILITY");
1110 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1111 }
1112 return ErrorCode::NO_ERROR;
1113 }
1114 if (trigger == SwitchTrigger::CURRENT_IME) {
1115 // PERMISSION_CONNECT_IME_ABILITY check temporarily reserved for application adaptation, will be deleted soon
1116 if (identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)) {
1117 return ErrorCode::NO_ERROR;
1118 }
1119 IMSA_HILOGE("not have PERMISSION_CONNECT_IME_ABILITY");
1120 // switchInfo.subName.empty() check temporarily reserved for application adaptation, will be deleted soon
1121 auto currentBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
1122 if (identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), currentBundleName)
1123 && !switchInfo.subName.empty()) {
1124 return ErrorCode::NO_ERROR;
1125 }
1126 IMSA_HILOGE("not current ime");
1127 /* return ErrorCode::ERROR_STATUS_PERMISSION_DENIED temporarily reserved for application adaptation,
1128 will be replaced by ERROR_NOT_CURRENT_IME soon */
1129 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1130 }
1131 return ErrorCode::ERROR_BAD_PARAMETERS;
1132 }
1133
IsStartInputTypePermitted()1134 bool InputMethodSystemAbility::IsStartInputTypePermitted()
1135 {
1136 auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultImeInfo(userId_);
1137 if (defaultIme == nullptr) {
1138 IMSA_HILOGE("failed to get default ime");
1139 return false;
1140 }
1141 auto tokenId = IPCSkeleton::GetCallingTokenID();
1142 if (identityChecker_->IsBundleNameValid(tokenId, defaultIme->prop.name)) {
1143 return true;
1144 }
1145 return identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId) && userSession_->IsBoundToClient();
1146 }
1147 } // namespace MiscServices
1148 } // namespace OHOS
1149