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_connect_callback_proxy.h"
21 #include "ability_manager_errors.h"
22 #include "ability_manager_interface.h"
23 #include "application_info.h"
24 #include "combination_key.h"
25 #include "common_event_support.h"
26 #include "errors.h"
27 #include "full_ime_info_manager.h"
28 #include "global.h"
29 #include "im_common_event_manager.h"
30 #include "ime_cfg_manager.h"
31 #include "ime_info_inquirer.h"
32 #include "input_client_info.h"
33 #include "input_method_utils.h"
34 #include "input_type_manager.h"
35 #include "ipc_skeleton.h"
36 #include "iservice_registry.h"
37 #include "itypes_util.h"
38 #include "key_event.h"
39 #include "mem_mgr_client.h"
40 #include "message_handler.h"
41 #include "native_token_info.h"
42 #include "os_account_adapter.h"
43 #include "scene_board_judgement.h"
44 #include "system_ability_definition.h"
45 #ifdef IMF_SCREENLOCK_MGR_ENABLE
46 #include "screenlock_manager.h"
47 #endif
48 #include "system_language_observer.h"
49 #include "user_session_manager.h"
50 #include "wms_connection_observer.h"
51
52 namespace OHOS {
53 namespace MiscServices {
54 using namespace MessageID;
55 using namespace AppExecFwk;
56 using namespace Security::AccessToken;
57 REGISTER_SYSTEM_ABILITY_BY_ID(InputMethodSystemAbility, INPUT_METHOD_SYSTEM_ABILITY_ID, true);
58 constexpr std::int32_t INIT_INTERVAL = 10000L;
59 constexpr const char *UNDEFINED = "undefined";
60 static const std::string PERMISSION_CONNECT_IME_ABILITY = "ohos.permission.CONNECT_IME_ABILITY";
61 std::shared_ptr<AppExecFwk::EventHandler> InputMethodSystemAbility::serviceHandler_;
62
InputMethodSystemAbility(int32_t systemAbilityId,bool runOnCreate)63 InputMethodSystemAbility::InputMethodSystemAbility(int32_t systemAbilityId, bool runOnCreate)
64 : SystemAbility(systemAbilityId, runOnCreate), state_(ServiceRunningState::STATE_NOT_START)
65 {
66 }
67
InputMethodSystemAbility()68 InputMethodSystemAbility::InputMethodSystemAbility() : state_(ServiceRunningState::STATE_NOT_START)
69 {
70 }
71
~InputMethodSystemAbility()72 InputMethodSystemAbility::~InputMethodSystemAbility()
73 {
74 stop_ = true;
75 Message *msg = new Message(MessageID::MSG_ID_QUIT_WORKER_THREAD, nullptr);
76 MessageHandler::Instance()->SendMessage(msg);
77 if (workThreadHandler.joinable()) {
78 workThreadHandler.join();
79 }
80 }
81
OnStart()82 void InputMethodSystemAbility::OnStart()
83 {
84 IMSA_HILOGI("InputMethodSystemAbility::OnStart start.");
85 if (!InputMethodSysEvent::GetInstance().StartTimerForReport()) {
86 IMSA_HILOGE("start sysevent timer failed!");
87 }
88 if (state_ == ServiceRunningState::STATE_RUNNING) {
89 IMSA_HILOGI("imsa service is already running.");
90 return;
91 }
92 InitServiceHandler();
93 Initialize();
94 int32_t ret = Init();
95 if (ret != ErrorCode::NO_ERROR) {
96 InputMethodSysEvent::GetInstance().ServiceFaultReporter("imf", ret);
97 auto callback = [=]() { Init(); };
98 serviceHandler_->PostTask(callback, INIT_INTERVAL);
99 IMSA_HILOGE("init failed. try again 10s later!");
100 }
101 InitHiTrace();
102 InputMethodSyncTrace tracer("InputMethodController Attach trace.");
103 InputmethodDump::GetInstance().AddDumpAllMethod([this](int fd) { this->DumpAllMethod(fd); });
104 IMSA_HILOGI("start imsa service success.");
105 return;
106 }
107
Dump(int fd,const std::vector<std::u16string> & args)108 int InputMethodSystemAbility::Dump(int fd, const std::vector<std::u16string> &args)
109 {
110 IMSA_HILOGD("InputMethodSystemAbility::Dump start.");
111 std::vector<std::string> argsStr;
112 for (auto item : args) {
113 argsStr.emplace_back(Str16ToStr8(item));
114 }
115 InputmethodDump::GetInstance().Dump(fd, argsStr);
116 return ERR_OK;
117 }
118
DumpAllMethod(int fd)119 void InputMethodSystemAbility::DumpAllMethod(int fd)
120 {
121 IMSA_HILOGD("InputMethodSystemAbility::DumpAllMethod start.");
122 auto ids = OsAccountAdapter::QueryActiveOsAccountIds();
123 if (ids.empty()) {
124 dprintf(fd, "\n - InputMethodSystemAbility::DumpAllMethod get Active Id failed.\n");
125 return;
126 }
127 dprintf(fd, "\n - DumpAllMethod get Active Id succeed,count=%zu,", ids.size());
128 for (auto id : ids) {
129 const auto ¶ms = ImeInfoInquirer::GetInstance().GetDumpInfo(id);
130 if (params.empty()) {
131 IMSA_HILOGD("userId: %{public}d the IME properties is empty.", id);
132 dprintf(fd, "\n - The IME properties about the Active Id %d is empty.\n", id);
133 continue;
134 }
135 dprintf(fd, "\n - The Active Id:%d get input method:\n%s\n", id, params.c_str());
136 }
137 IMSA_HILOGD("InputMethodSystemAbility::DumpAllMethod end.");
138 }
139
Init()140 int32_t InputMethodSystemAbility::Init()
141 {
142 bool isSuccess = Publish(this);
143 if (!isSuccess) {
144 return -1;
145 }
146 state_ = ServiceRunningState::STATE_RUNNING;
147 ImeCfgManager::GetInstance().Init();
148 ImeInfoInquirer::GetInstance().InitSystemConfig();
149 InitMonitors();
150 return ErrorCode::NO_ERROR;
151 }
152
UpdateUserInfo(int32_t userId)153 void InputMethodSystemAbility::UpdateUserInfo(int32_t userId)
154 {
155 IMSA_HILOGI("%{public}d switch to %{public}d.", userId_, userId);
156 userId_ = userId;
157 UserSessionManager::GetInstance().AddUserSession(userId_);
158 InputMethodSysEvent::GetInstance().SetUserId(userId_);
159 if (enableImeOn_.load()) {
160 EnableImeDataParser::GetInstance()->OnUserChanged(userId_);
161 }
162 if (enableSecurityMode_.load()) {
163 SecurityModeParser::GetInstance()->UpdateFullModeList(userId_);
164 }
165 UpdateUserLockState();
166 }
167
UpdateUserLockState()168 void InputMethodSystemAbility::UpdateUserLockState()
169 {
170 auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
171 if (session == nullptr) {
172 UserSessionManager::GetInstance().AddUserSession(userId_);
173 }
174 session = UserSessionManager::GetInstance().GetUserSession(userId_);
175 if (session == nullptr) {
176 IMSA_HILOGE("%{public}d session is nullptr!", userId_);
177 return;
178 }
179 session->UpdateUserLockState();
180 }
181
OnStop()182 void InputMethodSystemAbility::OnStop()
183 {
184 IMSA_HILOGI("OnStop start.");
185 FreezeManager::SetEventHandler(nullptr);
186 serviceHandler_ = nullptr;
187 state_ = ServiceRunningState::STATE_NOT_START;
188 Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 0, INPUT_METHOD_SYSTEM_ABILITY_ID);
189 }
190
InitServiceHandler()191 void InputMethodSystemAbility::InitServiceHandler()
192 {
193 IMSA_HILOGI("InitServiceHandler start.");
194 if (serviceHandler_ != nullptr) {
195 IMSA_HILOGE("InputMethodSystemAbility already init.");
196 return;
197 }
198 std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create("OS_InputMethodSystemAbility");
199 serviceHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
200 FreezeManager::SetEventHandler(serviceHandler_);
201
202 IMSA_HILOGI("InitServiceHandler succeeded.");
203 }
204
205 /**
206 * Initialization of Input method management service
207 * \n It's called after the service starts, before any transaction.
208 */
Initialize()209 void InputMethodSystemAbility::Initialize()
210 {
211 IMSA_HILOGI("InputMethodSystemAbility::Initialize.");
212 // init work thread to handle the messages
213 workThreadHandler = std::thread([this] { this->WorkThread(); });
214 identityChecker_ = std::make_shared<IdentityCheckerImpl>();
215 userId_ = OsAccountAdapter::MAIN_USER_ID;
216 UserSessionManager::GetInstance().SetEventHandler(serviceHandler_);
217 UserSessionManager::GetInstance().AddUserSession(userId_);
218 InputMethodSysEvent::GetInstance().SetUserId(userId_);
219 isScbEnable_.store(Rosen::SceneBoardJudgement::IsSceneBoardEnabled());
220 }
221
SubscribeCommonEvent()222 void InputMethodSystemAbility::SubscribeCommonEvent()
223 {
224 sptr<ImCommonEventManager> imCommonEventManager = ImCommonEventManager::GetInstance();
225 bool isSuccess = imCommonEventManager->SubscribeEvent();
226 if (isSuccess) {
227 IMSA_HILOGI("initialize subscribe service event success.");
228 return;
229 }
230
231 IMSA_HILOGE("failed, try again 10s later");
232 auto callback = [this]() { SubscribeCommonEvent(); };
233 serviceHandler_->PostTask(callback, INIT_INTERVAL);
234 }
235
PrepareInput(int32_t userId,InputClientInfo & clientInfo)236 int32_t InputMethodSystemAbility::PrepareInput(int32_t userId, InputClientInfo &clientInfo)
237 {
238 auto ret = GenerateClientInfo(userId, clientInfo);
239 if (ret != ErrorCode::NO_ERROR) {
240 return ret;
241 }
242 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
243 if (session == nullptr) {
244 IMSA_HILOGE("%{public}d session is nullptr", userId);
245 return ErrorCode::ERROR_NULL_POINTER;
246 }
247 return session->OnPrepareInput(clientInfo);
248 }
249
GenerateClientInfo(int32_t userId,InputClientInfo & clientInfo)250 int32_t InputMethodSystemAbility::GenerateClientInfo(int32_t userId, InputClientInfo &clientInfo)
251 {
252 if (clientInfo.client == nullptr || clientInfo.channel == nullptr) {
253 IMSA_HILOGE("client or channel is nullptr!");
254 return ErrorCode::ERROR_NULL_POINTER;
255 }
256 auto deathRecipient = new (std::nothrow) InputDeathRecipient();
257 if (deathRecipient == nullptr) {
258 IMSA_HILOGE("failed to new deathRecipient!");
259 return ErrorCode::ERROR_EX_NULL_POINTER;
260 }
261 clientInfo.pid = IPCSkeleton::GetCallingPid();
262 clientInfo.uid = IPCSkeleton::GetCallingUid();
263 clientInfo.userID = userId;
264 clientInfo.deathRecipient = deathRecipient;
265 auto tokenId = IPCSkeleton::GetCallingTokenID();
266 if (identityChecker_->IsFocusedUIExtension(tokenId)) {
267 clientInfo.uiExtensionTokenId = tokenId;
268 }
269 return ErrorCode::NO_ERROR;
270 }
271
ReleaseInput(sptr<IInputClient> client)272 int32_t InputMethodSystemAbility::ReleaseInput(sptr<IInputClient> client)
273 {
274 if (client == nullptr) {
275 IMSA_HILOGE("client is nullptr!");
276 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
277 }
278 auto userId = GetCallingUserId();
279 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
280 if (session == nullptr) {
281 IMSA_HILOGE("%{public}d session is nullptr", userId);
282 return ErrorCode::ERROR_NULL_POINTER;
283 }
284 return session->OnReleaseInput(client);
285 }
286
StartInput(InputClientInfo & inputClientInfo,sptr<IRemoteObject> & agent)287 int32_t InputMethodSystemAbility::StartInput(InputClientInfo &inputClientInfo, sptr<IRemoteObject> &agent)
288 {
289 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
290 if (!identityChecker_->IsBroker(tokenId) && !identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId)) {
291 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
292 }
293 auto userId = GetCallingUserId();
294 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
295 if (session == nullptr) {
296 IMSA_HILOGE("%{public}d session is nullptr", userId);
297 return ErrorCode::ERROR_NULL_POINTER;
298 }
299 if (session->GetCurrentClientPid() != IPCSkeleton::GetCallingPid()
300 && session->GetInactiveClientPid() != IPCSkeleton::GetCallingPid()) {
301 // notify inputStart when caller pid different from both current client and inactive client
302 inputClientInfo.isNotifyInputStart = true;
303 }
304 if (session->CheckPwdInputPatternConv(inputClientInfo)) {
305 inputClientInfo.needHide = true;
306 inputClientInfo.isNotifyInputStart = true;
307 }
308 if (!session->IsProxyImeEnable()) {
309 auto ret = CheckInputTypeOption(userId, inputClientInfo);
310 if (ret != ErrorCode::NO_ERROR) {
311 IMSA_HILOGE("%{public}d failed to CheckInputTypeOption.", userId);
312 return ret;
313 }
314 }
315 inputClientInfo.config.inputAttribute.bundleName = identityChecker_->GetBundleNameByToken(tokenId);
316 int32_t ret = PrepareInput(userId, inputClientInfo);
317 if (ret != ErrorCode::NO_ERROR) {
318 IMSA_HILOGE("failed to PrepareInput");
319 return ret;
320 }
321 return session->OnStartInput(inputClientInfo, agent);
322 }
323
CheckInputTypeOption(int32_t userId,InputClientInfo & inputClientInfo)324 int32_t InputMethodSystemAbility::CheckInputTypeOption(int32_t userId, InputClientInfo &inputClientInfo)
325 {
326 IMSA_HILOGI("SecurityFlag: %{public}d, IsSameTextInput: %{public}d, IsStarted: %{public}d, "
327 "IsSecurityImeStarted: %{public}d.",
328 inputClientInfo.config.inputAttribute.GetSecurityFlag(), !inputClientInfo.isNotifyInputStart,
329 InputTypeManager::GetInstance().IsStarted(), InputTypeManager::GetInstance().IsSecurityImeStarted());
330 if (inputClientInfo.config.inputAttribute.GetSecurityFlag()) {
331 if (!InputTypeManager::GetInstance().IsStarted()) {
332 IMSA_HILOGD("SecurityFlag, input type is not started, start.");
333 // if need to switch ime, no need to hide panel first.
334 NeedHideWhenSwitchInputType(userId, inputClientInfo.needHide);
335 return StartInputType(userId, InputType::SECURITY_INPUT);
336 }
337 if (!inputClientInfo.isNotifyInputStart) {
338 IMSA_HILOGD("SecurityFlag, same textField, input type is started, not deal.");
339 return ErrorCode::NO_ERROR;
340 }
341 if (!InputTypeManager::GetInstance().IsSecurityImeStarted()) {
342 IMSA_HILOGD("SecurityFlag, new textField, input type is started, but it is not security, switch.");
343 NeedHideWhenSwitchInputType(userId, inputClientInfo.needHide);
344 return StartInputType(userId, InputType::SECURITY_INPUT);
345 }
346 IMSA_HILOGD("SecurityFlag, other condition, not deal.");
347 return ErrorCode::NO_ERROR;
348 }
349 if (!inputClientInfo.isNotifyInputStart) {
350 IMSA_HILOGD("NormalFlag, same textField, not deal.");
351 return ErrorCode::NO_ERROR;
352 }
353 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
354 if (session == nullptr) {
355 IMSA_HILOGE("%{public}d session is nullptr", userId);
356 return ErrorCode::ERROR_NULL_POINTER;
357 }
358 if (InputTypeManager::GetInstance().IsStarted()) {
359 IMSA_HILOGD("NormalFlag, diff textField, input type started, restore.");
360 session->RestoreCurrentImeSubType();
361 }
362 return session->RestoreCurrentIme();
363 }
364
ShowInput(sptr<IInputClient> client)365 int32_t InputMethodSystemAbility::ShowInput(sptr<IInputClient> client)
366 {
367 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
368 auto userId = GetCallingUserId();
369 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
370 if (session == nullptr) {
371 IMSA_HILOGE("%{public}d session is nullptr", userId);
372 return ErrorCode::ERROR_NULL_POINTER;
373 }
374 if (!identityChecker_->IsBroker(tokenId)) {
375 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
376 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
377 }
378 }
379 if (client == nullptr) {
380 IMSA_HILOGE("client is nullptr");
381 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
382 }
383 return session->OnShowInput(client);
384 }
385
HideInput(sptr<IInputClient> client)386 int32_t InputMethodSystemAbility::HideInput(sptr<IInputClient> client)
387 {
388 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
389 auto userId = GetCallingUserId();
390 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
391 if (session == nullptr) {
392 IMSA_HILOGE("%{public}d session is nullptr", userId);
393 return ErrorCode::ERROR_NULL_POINTER;
394 }
395 if (!identityChecker_->IsBroker(tokenId)) {
396 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
397 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
398 }
399 }
400 if (client == nullptr) {
401 IMSA_HILOGE("client is nullptr");
402 return ErrorCode::ERROR_CLIENT_NULL_POINTER;
403 }
404 return session->OnHideInput(client);
405 }
406
StopInputSession()407 int32_t InputMethodSystemAbility::StopInputSession()
408 {
409 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
410 auto userId = GetCallingUserId();
411 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
412 if (session == nullptr) {
413 IMSA_HILOGE("%{public}d session is nullptr", userId);
414 return ErrorCode::ERROR_NULL_POINTER;
415 }
416 if (!identityChecker_->IsBroker(tokenId)) {
417 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
418 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
419 }
420 }
421 return session->OnHideCurrentInput();
422 }
423
RequestShowInput()424 int32_t InputMethodSystemAbility::RequestShowInput()
425 {
426 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
427 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId)
428 && !identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
429 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
430 }
431 auto userId = GetCallingUserId();
432 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
433 if (session == nullptr) {
434 IMSA_HILOGE("%{public}d session is nullptr", userId);
435 return ErrorCode::ERROR_NULL_POINTER;
436 }
437 return session->OnRequestShowInput();
438 }
439
RequestHideInput()440 int32_t InputMethodSystemAbility::RequestHideInput()
441 {
442 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
443 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId)
444 && !identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
445 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
446 }
447 auto userId = GetCallingUserId();
448 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
449 if (session == nullptr) {
450 IMSA_HILOGE("%{public}d session is nullptr", userId);
451 return ErrorCode::ERROR_NULL_POINTER;
452 }
453 return session->OnRequestHideInput();
454 }
455
SetCoreAndAgent(const sptr<IInputMethodCore> & core,const sptr<IRemoteObject> & agent)456 int32_t InputMethodSystemAbility::SetCoreAndAgent(const sptr<IInputMethodCore> &core, const sptr<IRemoteObject> &agent)
457 {
458 IMSA_HILOGD("InputMethodSystemAbility start.");
459 auto userId = GetCallingUserId();
460 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
461 if (session == nullptr) {
462 IMSA_HILOGE("%{public}d session is nullptr", userId);
463 return ErrorCode::ERROR_NULL_POINTER;
464 }
465 if (identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
466 return session->OnRegisterProxyIme(core, agent);
467 }
468 if (!IsCurrentIme(userId)) {
469 IMSA_HILOGE("not current ime, userId:%{public}d", userId);
470 return ErrorCode::ERROR_NOT_CURRENT_IME;
471 }
472 return session->OnSetCoreAndAgent(core, agent);
473 }
474
InitConnect()475 int32_t InputMethodSystemAbility::InitConnect()
476 {
477 IMSA_HILOGD("InputMethodSystemAbility init connect.");
478 auto userId = GetCallingUserId();
479 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
480 if (session == nullptr) {
481 IMSA_HILOGE("%{public}d session is nullptr", userId);
482 return ErrorCode::ERROR_NULL_POINTER;
483 }
484 if (!IsCurrentIme(userId)) {
485 return ErrorCode::ERROR_NOT_CURRENT_IME;
486 }
487 return session->InitConnect(IPCSkeleton::GetCallingPid());
488 }
489
HideCurrentInput()490 int32_t InputMethodSystemAbility::HideCurrentInput()
491 {
492 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
493 auto userId = GetCallingUserId();
494 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
495 if (session == nullptr) {
496 IMSA_HILOGE("%{public}d session is nullptr", userId);
497 return ErrorCode::ERROR_NULL_POINTER;
498 }
499 if (identityChecker_->IsBroker(tokenId)) {
500 return session->OnHideCurrentInput();
501 }
502 if (!identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
503 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
504 }
505 return session->OnHideCurrentInput();
506 }
507
ShowCurrentInput()508 int32_t InputMethodSystemAbility::ShowCurrentInput()
509 {
510 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
511 auto userId = GetCallingUserId();
512 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
513 if (session == nullptr) {
514 IMSA_HILOGE("%{public}d session is nullptr", userId);
515 return ErrorCode::ERROR_NULL_POINTER;
516 }
517 if (identityChecker_->IsBroker(tokenId)) {
518 return session->OnShowCurrentInput();
519 }
520 if (!identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
521 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
522 }
523 return session->OnShowCurrentInput();
524 }
525
PanelStatusChange(const InputWindowStatus & status,const ImeWindowInfo & info)526 int32_t InputMethodSystemAbility::PanelStatusChange(const InputWindowStatus &status, const ImeWindowInfo &info)
527 {
528 auto userId = GetCallingUserId();
529 if (!IsCurrentIme(userId)) {
530 IMSA_HILOGE("not current ime!");
531 return ErrorCode::ERROR_NOT_CURRENT_IME;
532 }
533 auto commonEventManager = ImCommonEventManager::GetInstance();
534 if (commonEventManager != nullptr) {
535 auto ret = ImCommonEventManager::GetInstance()->PublishPanelStatusChangeEvent(userId, status, info);
536 IMSA_HILOGD("public panel status change event: %{public}d", ret);
537 }
538 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
539 if (session == nullptr) {
540 IMSA_HILOGE("%{public}d session is nullptr", userId);
541 return ErrorCode::ERROR_NULL_POINTER;
542 }
543 return session->OnPanelStatusChange(status, info);
544 }
545
UpdateListenEventFlag(InputClientInfo & clientInfo,uint32_t eventFlag)546 int32_t InputMethodSystemAbility::UpdateListenEventFlag(InputClientInfo &clientInfo, uint32_t eventFlag)
547 {
548 IMSA_HILOGI("finalEventFlag: %{public}u, eventFlag: %{public}u.", clientInfo.eventFlag, eventFlag);
549 if (EventStatusManager::IsImeHideOn(eventFlag) || EventStatusManager::IsImeShowOn(eventFlag)) {
550 if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()) &&
551 !identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
552 IMSA_HILOGE("not system application!");
553 return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
554 }
555 }
556 auto userId = GetCallingUserId();
557 auto ret = GenerateClientInfo(userId, clientInfo);
558 if (ret != ErrorCode::NO_ERROR) {
559 return ret;
560 }
561 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
562 if (session == nullptr) {
563 IMSA_HILOGE("%{public}d session is nullptr", userId);
564 return ErrorCode::ERROR_NULL_POINTER;
565 }
566 return session->OnUpdateListenEventFlag(clientInfo);
567 }
568
IsCurrentIme()569 bool InputMethodSystemAbility::IsCurrentIme()
570 {
571 return IsCurrentIme(GetCallingUserId());
572 }
573
IsInputTypeSupported(InputType type)574 bool InputMethodSystemAbility::IsInputTypeSupported(InputType type)
575 {
576 return InputTypeManager::GetInstance().IsSupported(type);
577 }
578
StartInputType(InputType type)579 int32_t InputMethodSystemAbility::StartInputType(InputType type)
580 {
581 return StartInputType(GetCallingUserId(), type);
582 }
583
ExitCurrentInputType()584 int32_t InputMethodSystemAbility::ExitCurrentInputType()
585 {
586 auto userId = GetCallingUserId();
587 auto ret = IsDefaultImeFromTokenId(userId, IPCSkeleton::GetCallingTokenID());
588 if (ret != ErrorCode::NO_ERROR) {
589 IMSA_HILOGE("not default ime.");
590 return ErrorCode::ERROR_NOT_DEFAULT_IME;
591 }
592 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
593 if (session == nullptr) {
594 IMSA_HILOGE("%{public}d session is nullptr", userId);
595 return ErrorCode::ERROR_NULL_POINTER;
596 }
597 if (session->CheckSecurityMode()) {
598 return StartInputType(userId, InputType::SECURITY_INPUT);
599 }
600 auto typeIme = InputTypeManager::GetInstance().GetCurrentIme();
601 auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
602 if (cfgIme->bundleName == typeIme.bundleName) {
603 return session->RestoreCurrentImeSubType();
604 }
605 return session->RestoreCurrentIme();
606 }
607
IsDefaultIme()608 int32_t InputMethodSystemAbility::IsDefaultIme()
609 {
610 return IsDefaultImeFromTokenId(GetCallingUserId(), IPCSkeleton::GetCallingTokenID());
611 }
612
IsDefaultImeFromTokenId(int32_t userId,uint32_t tokenId)613 int32_t InputMethodSystemAbility::IsDefaultImeFromTokenId(int32_t userId, uint32_t tokenId)
614 {
615 auto prop = std::make_shared<Property>();
616 auto ret = ImeInfoInquirer::GetInstance().GetDefaultInputMethod(userId, prop);
617 if (ret != ErrorCode::NO_ERROR || prop == nullptr) {
618 IMSA_HILOGE("failed to get default ime!");
619 return ErrorCode::ERROR_PERSIST_CONFIG;
620 }
621 if (!identityChecker_->IsBundleNameValid(tokenId, prop->name)) {
622 return ErrorCode::ERROR_NOT_DEFAULT_IME;
623 }
624 return ErrorCode::NO_ERROR;
625 }
626
IsCurrentImeByPid(int32_t pid)627 bool InputMethodSystemAbility::IsCurrentImeByPid(int32_t pid)
628 {
629 if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID()) &&
630 !identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
631 IMSA_HILOGE("not system application or system ability!");
632 return false;
633 }
634 auto userId = GetCallingUserId();
635 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
636 if (session == nullptr) {
637 IMSA_HILOGE("%{public}d session is nullptr", userId);
638 return false;
639 }
640 return session->IsCurrentImeByPid(pid);
641 }
642
IsPanelShown(const PanelInfo & panelInfo,bool & isShown)643 int32_t InputMethodSystemAbility::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
644 {
645 if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) {
646 IMSA_HILOGE("not system application!");
647 return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
648 }
649 auto userId = GetCallingUserId();
650 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
651 if (session == nullptr) {
652 IMSA_HILOGE("%{public}d session is nullptr", userId);
653 return ErrorCode::ERROR_NULL_POINTER;
654 }
655 return session->IsPanelShown(panelInfo, isShown);
656 }
657
DisplayOptionalInputMethod()658 int32_t InputMethodSystemAbility::DisplayOptionalInputMethod()
659 {
660 IMSA_HILOGD("InputMethodSystemAbility start.");
661 return OnDisplayOptionalInputMethod();
662 }
663
SwitchInputMethod(const std::string & bundleName,const std::string & subName,SwitchTrigger trigger)664 int32_t InputMethodSystemAbility::SwitchInputMethod(
665 const std::string &bundleName, const std::string &subName, SwitchTrigger trigger)
666 {
667 // IMSA not check permission, add this verify for prevent counterfeit
668 if (trigger == SwitchTrigger::IMSA) {
669 IMSA_HILOGW("caller counterfeit!");
670 return ErrorCode::ERROR_BAD_PARAMETERS;
671 }
672 SwitchInfo switchInfo = { std::chrono::system_clock::now(), bundleName, subName };
673 int32_t userId = GetCallingUserId();
674 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
675 if (session == nullptr) {
676 IMSA_HILOGE("%{public}d session is nullptr", userId);
677 return ErrorCode::ERROR_NULL_POINTER;
678 }
679 if (enableImeOn_.load() && !EnableImeDataParser::GetInstance()->CheckNeedSwitch(switchInfo, userId)) {
680 IMSA_HILOGW("Enable mode off or switch is not enable, stopped!");
681 return ErrorCode::ERROR_ENABLE_IME;
682 }
683 auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
684 if (switchInfo.subName.empty() && switchInfo.bundleName == currentImeCfg->bundleName) {
685 switchInfo.subName = currentImeCfg->subName;
686 }
687 switchInfo.timestamp = std::chrono::system_clock::now();
688 session->GetSwitchQueue().Push(switchInfo);
689 return InputTypeManager::GetInstance().IsInputType({ bundleName, subName })
690 ? OnStartInputType(userId, switchInfo, true)
691 : OnSwitchInputMethod(userId, switchInfo, trigger);
692 }
693
EnableIme(const std::string & bundleName)694 bool InputMethodSystemAbility::EnableIme(const std::string &bundleName)
695 {
696 if (CheckEnableAndSwitchPermission() != ErrorCode::NO_ERROR) {
697 IMSA_HILOGE("Check enable ime value failed!");
698 return false;
699 }
700 int32_t userId = GetCallingUserId();
701 return SettingsDataUtils::GetInstance()->EnableIme(userId, bundleName);
702 }
703
OnSwitchInputMethod(int32_t userId,const SwitchInfo & switchInfo,SwitchTrigger trigger)704 int32_t InputMethodSystemAbility::OnSwitchInputMethod(int32_t userId, const SwitchInfo &switchInfo,
705 SwitchTrigger trigger)
706 {
707 InputMethodSysEvent::GetInstance().RecordEvent(IMEBehaviour::CHANGE_IME);
708 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
709 if (session == nullptr) {
710 IMSA_HILOGE("%{public}d session is nullptr", userId);
711 return ErrorCode::ERROR_NULL_POINTER;
712 }
713 if (!session->GetSwitchQueue().IsReady(switchInfo)) {
714 IMSA_HILOGD("start wait.");
715 session->GetSwitchQueue().Wait(switchInfo);
716 }
717 IMSA_HILOGI("start switch %{public}s|%{public}s.", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
718 int32_t ret = CheckSwitchPermission(userId, switchInfo, trigger);
719 if (ret != ErrorCode::NO_ERROR) {
720 InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ErrorCode::ERROR_STATUS_PERMISSION_DENIED,
721 switchInfo.bundleName, "switch input method failed!");
722 session->GetSwitchQueue().Pop();
723 return ret;
724 }
725 auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId, switchInfo.bundleName, switchInfo.subName);
726 if (info == nullptr) {
727 session->GetSwitchQueue().Pop();
728 return ErrorCode::ERROR_BAD_PARAMETERS;
729 }
730 InputTypeManager::GetInstance().Set(false);
731 {
732 InputMethodSyncTrace tracer("InputMethodSystemAbility_OnSwitchInputMethod");
733 std::string targetImeName = info->prop.name + "/" + info->prop.id;
734 ImeCfgManager::GetInstance().ModifyImeCfg({ userId, targetImeName, info->subProp.id, true });
735 auto targetIme = std::make_shared<ImeNativeCfg>(ImeNativeCfg {
736 targetImeName, info->prop.name, switchInfo.subName.empty() ? "" : info->subProp.id, info->prop.id });
737 if (!session->StartIme(targetIme)) {
738 InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ret, switchInfo.bundleName,
739 "switch input method failed!");
740 session->GetSwitchQueue().Pop();
741 return ErrorCode::ERROR_IME_START_FAILED;
742 }
743 GetValidSubtype(switchInfo.subName, info);
744 session->NotifyImeChangeToClients(info->prop, info->subProp);
745 ret = session->SwitchSubtype(info->subProp);
746 }
747 session->GetSwitchQueue().Pop();
748 ret = info->isSpecificSubName ? ret : ErrorCode::NO_ERROR;
749 if (ret != ErrorCode::NO_ERROR) {
750 InputMethodSysEvent::GetInstance().InputmethodFaultReporter(ret, switchInfo.bundleName,
751 "switch input method subtype failed!");
752 }
753 return ret;
754 }
755
GetValidSubtype(const std::string & subName,const std::shared_ptr<ImeInfo> & info)756 void InputMethodSystemAbility::GetValidSubtype(const std::string &subName, const std::shared_ptr<ImeInfo> &info)
757 {
758 if (subName.empty()) {
759 IMSA_HILOGW("undefined subtype");
760 info->subProp.id = UNDEFINED;
761 info->subProp.name = UNDEFINED;
762 }
763 }
764
OnStartInputType(int32_t userId,const SwitchInfo & switchInfo,bool isCheckPermission)765 int32_t InputMethodSystemAbility::OnStartInputType(int32_t userId, const SwitchInfo &switchInfo,
766 bool isCheckPermission)
767 {
768 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
769 if (session == nullptr) {
770 IMSA_HILOGE("%{public}d session is nullptr", userId);
771 return ErrorCode::ERROR_NULL_POINTER;
772 }
773 if (!session->GetSwitchQueue().IsReady(switchInfo)) {
774 IMSA_HILOGD("start wait.");
775 session->GetSwitchQueue().Wait(switchInfo);
776 }
777 IMSA_HILOGD("start switch %{public}s|%{public}s.", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
778 if (isCheckPermission && !IsStartInputTypePermitted(userId)) {
779 IMSA_HILOGE("not permitted to start input type!");
780 session->GetSwitchQueue().Pop();
781 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
782 }
783 if (!IsNeedSwitch(userId, switchInfo.bundleName, switchInfo.subName)) {
784 IMSA_HILOGI("no need to switch.");
785 session->GetSwitchQueue().Pop();
786 return ErrorCode::NO_ERROR;
787 }
788 int32_t ret = SwitchInputType(userId, switchInfo);
789 session->GetSwitchQueue().Pop();
790 return ret;
791 }
792
IsNeedSwitch(int32_t userId,const std::string & bundleName,const std::string & subName)793 bool InputMethodSystemAbility::IsNeedSwitch(int32_t userId, const std::string &bundleName,
794 const std::string &subName)
795 {
796 if (InputTypeManager::GetInstance().IsStarted()) {
797 ImeIdentification target = { bundleName, subName };
798 return !(target == InputTypeManager::GetInstance().GetCurrentIme());
799 }
800 auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
801 IMSA_HILOGI("currentIme: %{public}s/%{public}s, targetIme: %{public}s/%{public}s.",
802 currentImeCfg->bundleName.c_str(), currentImeCfg->subName.c_str(), bundleName.c_str(), subName.c_str());
803 if ((subName.empty() && bundleName == currentImeCfg->bundleName) ||
804 (!subName.empty() && subName == currentImeCfg->subName && currentImeCfg->bundleName == bundleName)) {
805 IMSA_HILOGI("no need to switch");
806 return false;
807 }
808 return true;
809 }
810
Switch(int32_t userId,const std::string & bundleName,const std::shared_ptr<ImeInfo> & info)811 int32_t InputMethodSystemAbility::Switch(int32_t userId, const std::string &bundleName,
812 const std::shared_ptr<ImeInfo> &info)
813 {
814 auto currentImeBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName;
815 if (bundleName != currentImeBundleName) {
816 IMSA_HILOGI("switch input method to: %{public}s", bundleName.c_str());
817 return SwitchExtension(userId, info);
818 }
819 auto currentInputType = InputTypeManager::GetInstance().GetCurrentIme();
820 auto isInputTypeStarted = InputTypeManager::GetInstance().IsStarted();
821 if (isInputTypeStarted && bundleName != currentInputType.bundleName) {
822 IMSA_HILOGI("right click on state, switch input method to: %{public}s", bundleName.c_str());
823 return SwitchExtension(userId, info);
824 }
825 return SwitchSubType(userId, info);
826 }
827
828 // Switch the current InputMethodExtension to the new InputMethodExtension
SwitchExtension(int32_t userId,const std::shared_ptr<ImeInfo> & info)829 int32_t InputMethodSystemAbility::SwitchExtension(int32_t userId, const std::shared_ptr<ImeInfo> &info)
830 {
831 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
832 if (session == nullptr) {
833 IMSA_HILOGE("%{public}d session is nullptr", userId);
834 return ErrorCode::ERROR_NULL_POINTER;
835 }
836 std::string targetImeName = info->prop.name + "/" + info->prop.id;
837 ImeCfgManager::GetInstance().ModifyImeCfg({ userId, targetImeName, info->subProp.id, false });
838 ImeNativeCfg targetIme = { targetImeName, info->prop.name, info->subProp.id, info->prop.id };
839 if (!session->StartIme(std::make_shared<ImeNativeCfg>(targetIme))) {
840 IMSA_HILOGE("start input method failed!");
841 return ErrorCode::ERROR_IME_START_FAILED;
842 }
843 session->NotifyImeChangeToClients(info->prop, info->subProp);
844 GetValidSubtype("", info);
845 session->SwitchSubtype(info->subProp);
846 return ErrorCode::NO_ERROR;
847 }
848
849 // Inform current InputMethodExtension to switch subtype
SwitchSubType(int32_t userId,const std::shared_ptr<ImeInfo> & info)850 int32_t InputMethodSystemAbility::SwitchSubType(int32_t userId, const std::shared_ptr<ImeInfo> &info)
851 {
852 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
853 if (session == nullptr) {
854 IMSA_HILOGE("%{public}d session is nullptr", userId);
855 return ErrorCode::ERROR_NULL_POINTER;
856 }
857 auto ret = session->SwitchSubtype(info->subProp);
858 if (ret != ErrorCode::NO_ERROR) {
859 IMSA_HILOGE("failed to inform ime to switch subtype, ret: %{public}d!", ret);
860 return ret;
861 }
862 auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->imeId;
863 ImeCfgManager::GetInstance().ModifyImeCfg({ userId, currentIme, info->subProp.id, false });
864 session->NotifyImeChangeToClients(info->prop, info->subProp);
865 return ErrorCode::NO_ERROR;
866 }
867
SwitchInputType(int32_t userId,const SwitchInfo & switchInfo)868 int32_t InputMethodSystemAbility::SwitchInputType(int32_t userId, const SwitchInfo &switchInfo)
869 {
870 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
871 if (session == nullptr) {
872 IMSA_HILOGE("%{public}d session is nullptr", userId);
873 return ErrorCode::ERROR_NULL_POINTER;
874 }
875 auto targetIme = session->GetImeNativeCfg(userId, switchInfo.bundleName, switchInfo.subName);
876 if (targetIme == nullptr) {
877 IMSA_HILOGE("targetIme is nullptr!");
878 return ErrorCode::ERROR_NULL_POINTER;
879 }
880 if (!session->StartIme(targetIme)) {
881 IMSA_HILOGE("start input method failed!");
882 return ErrorCode::ERROR_IME_START_FAILED;
883 }
884 int32_t ret = session->SwitchSubtype({ .name = switchInfo.bundleName, .id = switchInfo.subName });
885 if (ret != ErrorCode::NO_ERROR) {
886 IMSA_HILOGE("switch subtype failed!");
887 return ret;
888 }
889 InputTypeManager::GetInstance().Set(true, { switchInfo.bundleName, switchInfo.subName });
890 return ErrorCode::NO_ERROR;
891 }
892
893 // Deprecated because of no permission check, kept for compatibility
HideCurrentInputDeprecated()894 int32_t InputMethodSystemAbility::HideCurrentInputDeprecated()
895 {
896 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
897 int32_t userId = GetCallingUserId();
898 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
899 if (session == nullptr) {
900 IMSA_HILOGE("%{public}d session is nullptr", userId);
901 return ErrorCode::ERROR_NULL_POINTER;
902 }
903 if (!identityChecker_->IsBroker(tokenId)) {
904 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
905 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
906 }
907 }
908 return session->OnHideCurrentInput();
909 }
910
ShowCurrentInputDeprecated()911 int32_t InputMethodSystemAbility::ShowCurrentInputDeprecated()
912 {
913 AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
914 int32_t userId = GetCallingUserId();
915 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
916 if (session == nullptr) {
917 IMSA_HILOGE("%{public}d session is nullptr", userId);
918 return ErrorCode::ERROR_NULL_POINTER;
919 }
920 if (!identityChecker_->IsBroker(tokenId)) {
921 if (!identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId, session->GetCurrentClientPid())) {
922 return ErrorCode::ERROR_CLIENT_NOT_FOCUSED;
923 }
924 }
925 return session->OnShowCurrentInput();
926 }
927
GetCurrentInputMethod()928 std::shared_ptr<Property> InputMethodSystemAbility::GetCurrentInputMethod()
929 {
930 return ImeInfoInquirer::GetInstance().GetCurrentInputMethod(GetCallingUserId());
931 }
932
IsDefaultImeSet()933 bool InputMethodSystemAbility::IsDefaultImeSet()
934 {
935 return ImeInfoInquirer::GetInstance().IsDefaultImeSet(GetCallingUserId());
936 }
937
GetCurrentInputMethodSubtype()938 std::shared_ptr<SubProperty> InputMethodSystemAbility::GetCurrentInputMethodSubtype()
939 {
940 return ImeInfoInquirer::GetInstance().GetCurrentSubtype(GetCallingUserId());
941 }
942
GetDefaultInputMethod(std::shared_ptr<Property> & prop,bool isBrief)943 int32_t InputMethodSystemAbility::GetDefaultInputMethod(std::shared_ptr<Property> &prop, bool isBrief)
944 {
945 return ImeInfoInquirer::GetInstance().GetDefaultInputMethod(GetCallingUserId(), prop, isBrief);
946 }
947
GetInputMethodConfig(OHOS::AppExecFwk::ElementName & inputMethodConfig)948 int32_t InputMethodSystemAbility::GetInputMethodConfig(OHOS::AppExecFwk::ElementName &inputMethodConfig)
949 {
950 return ImeInfoInquirer::GetInstance().GetInputMethodConfig(GetCallingUserId(), inputMethodConfig);
951 }
952
ListInputMethod(InputMethodStatus status,std::vector<Property> & props)953 int32_t InputMethodSystemAbility::ListInputMethod(InputMethodStatus status, std::vector<Property> &props)
954 {
955 return ImeInfoInquirer::GetInstance().ListInputMethod(GetCallingUserId(), status, props, enableImeOn_.load());
956 }
957
ListCurrentInputMethodSubtype(std::vector<SubProperty> & subProps)958 int32_t InputMethodSystemAbility::ListCurrentInputMethodSubtype(std::vector<SubProperty> &subProps)
959 {
960 return ImeInfoInquirer::GetInstance().ListCurrentInputMethodSubtype(GetCallingUserId(), subProps);
961 }
962
ListInputMethodSubtype(const std::string & bundleName,std::vector<SubProperty> & subProps)963 int32_t InputMethodSystemAbility::ListInputMethodSubtype(
964 const std::string &bundleName, std::vector<SubProperty> &subProps)
965 {
966 return ImeInfoInquirer::GetInstance().ListInputMethodSubtype(GetCallingUserId(), bundleName, subProps);
967 }
968
969 /**
970 * Work Thread of input method management service
971 * \n Remote commands which may change the state or data in the service will be handled sequentially in this thread.
972 */
WorkThread()973 void InputMethodSystemAbility::WorkThread()
974 {
975 pthread_setname_np(pthread_self(), "OS_IMSAWorkThread");
976 while (!stop_) {
977 Message *msg = MessageHandler::Instance()->GetMessage();
978 switch (msg->msgId_) {
979 case MSG_ID_USER_START: {
980 OnUserStarted(msg);
981 break;
982 }
983 case MSG_ID_USER_REMOVED: {
984 OnUserRemoved(msg);
985 break;
986 }
987 case MSG_ID_USER_STOP: {
988 OnUserStop(msg);
989 break;
990 }
991 case MSG_ID_HIDE_KEYBOARD_SELF: {
992 OnHideKeyboardSelf(msg);
993 break;
994 }
995 case MSG_ID_BUNDLE_SCAN_FINISHED: {
996 break;
997 }
998 case MSG_ID_DATA_SHARE_READY: {
999 HandleDataShareReady();
1000 break;
1001 }
1002 case MSG_ID_PACKAGE_ADDED:
1003 case MSG_ID_PACKAGE_CHANGED:
1004 case MSG_ID_PACKAGE_REMOVED: {
1005 HandlePackageEvent(msg);
1006 break;
1007 }
1008 case MSG_ID_SYS_LANGUAGE_CHANGED: {
1009 FullImeInfoManager::GetInstance().Update();
1010 break;
1011 }
1012 case MSG_ID_BOOT_COMPLETED:
1013 case MSG_ID_OS_ACCOUNT_STARTED: {
1014 FullImeInfoManager::GetInstance().Init();
1015 break;
1016 }
1017 case MSG_ID_USER_UNLOCKED: {
1018 OnUserUnlocked(msg);
1019 break;
1020 }
1021 default: {
1022 IMSA_HILOGD("the message is %{public}d.", msg->msgId_);
1023 break;
1024 }
1025 }
1026 delete msg;
1027 }
1028 }
1029
1030 /**
1031 * Called when a user is started. (EVENT_USER_STARTED is received)
1032 * \n Run in work thread of input method management service
1033 * \param msg the parameters are saved in msg->msgContent_
1034 * \return ErrorCode
1035 */
OnUserStarted(const Message * msg)1036 int32_t InputMethodSystemAbility::OnUserStarted(const Message *msg)
1037 {
1038 if (msg->msgContent_ == nullptr) {
1039 IMSA_HILOGE("msgContent_ is nullptr.");
1040 return ErrorCode::ERROR_NULL_POINTER;
1041 }
1042 auto newUserId = msg->msgContent_->ReadInt32();
1043 FullImeInfoManager::GetInstance().Add(newUserId);
1044 // if scb enable, deal when receive wmsConnected.
1045 if (isScbEnable_.load()) {
1046 return ErrorCode::NO_ERROR;
1047 }
1048 if (newUserId == userId_) {
1049 return ErrorCode::NO_ERROR;
1050 }
1051 HandleUserSwitched(newUserId);
1052 return ErrorCode::NO_ERROR;
1053 }
1054
OnUserRemoved(const Message * msg)1055 int32_t InputMethodSystemAbility::OnUserRemoved(const Message *msg)
1056 {
1057 if (msg == nullptr || msg->msgContent_ == nullptr) {
1058 IMSA_HILOGE("Aborted! Message is nullptr.");
1059 return ErrorCode::ERROR_NULL_POINTER;
1060 }
1061 auto userId = msg->msgContent_->ReadInt32();
1062 IMSA_HILOGI("start: %{public}d", userId);
1063 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1064 if (session != nullptr) {
1065 session->StopCurrentIme();
1066 UserSessionManager::GetInstance().RemoveUserSession(userId);
1067 }
1068 ImeCfgManager::GetInstance().DeleteImeCfg(userId);
1069 FullImeInfoManager::GetInstance().Delete(userId);
1070 return ErrorCode::NO_ERROR;
1071 }
1072
OnUserStop(const Message * msg)1073 int32_t InputMethodSystemAbility::OnUserStop(const Message *msg)
1074 {
1075 if (msg == nullptr || msg->msgContent_ == nullptr) {
1076 IMSA_HILOGE("Aborted! Message is nullptr.");
1077 return ErrorCode::ERROR_NULL_POINTER;
1078 }
1079 auto userId = msg->msgContent_->ReadInt32();
1080 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1081 if (session == nullptr) {
1082 IMSA_HILOGE("%{public}d session is nullptr", userId);
1083 return ErrorCode::ERROR_NULL_POINTER;
1084 }
1085 session->StopCurrentIme();
1086 return ErrorCode::NO_ERROR;
1087 }
1088
OnHideKeyboardSelf(const Message * msg)1089 int32_t InputMethodSystemAbility::OnHideKeyboardSelf(const Message *msg)
1090 {
1091 if (msg == nullptr || msg->msgContent_ == nullptr) {
1092 IMSA_HILOGE("Aborted! Message is nullptr.");
1093 return ErrorCode::ERROR_NULL_POINTER;
1094 }
1095 auto userId = msg->msgContent_->ReadInt32();
1096 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1097 if (session == nullptr) {
1098 IMSA_HILOGE("%{public}d session is nullptr", userId);
1099 return ErrorCode::ERROR_NULL_POINTER;
1100 }
1101 session->OnHideSoftKeyBoardSelf();
1102 return ErrorCode::NO_ERROR;
1103 }
1104
HandlePackageEvent(const Message * msg)1105 int32_t InputMethodSystemAbility::HandlePackageEvent(const Message *msg)
1106 {
1107 MessageParcel *data = msg->msgContent_;
1108 if (data == nullptr) {
1109 IMSA_HILOGD("data is nullptr.");
1110 return ErrorCode::ERROR_NULL_POINTER;
1111 }
1112 int32_t userId = 0;
1113 std::string packageName;
1114 if (!ITypesUtil::Unmarshal(*data, userId, packageName)) {
1115 IMSA_HILOGE("failed to read message parcel");
1116 return ErrorCode::ERROR_EX_PARCELABLE;
1117 }
1118 if (msg->msgId_ == MSG_ID_PACKAGE_CHANGED) {
1119 return FullImeInfoManager::GetInstance().Update(userId, packageName);
1120 }
1121 if (msg->msgId_ == MSG_ID_PACKAGE_ADDED) {
1122 return FullImeInfoManager::GetInstance().Add(userId, packageName);
1123 }
1124 if (msg->msgId_ == MSG_ID_PACKAGE_REMOVED) {
1125 return OnPackageRemoved(userId, packageName);
1126 }
1127 return ErrorCode::NO_ERROR;
1128 }
1129
1130 /**
1131 * Called when a package is removed.
1132 * \n Run in work thread of input method management service
1133 * \param msg the parameters are saved in msg->msgContent_
1134 * \return ErrorCode::NO_ERROR
1135 * \return ErrorCode::ERROR_USER_NOT_UNLOCKED user not unlocked
1136 * \return ErrorCode::ERROR_BAD_PARAMETERS bad parameter
1137 */
OnPackageRemoved(int32_t userId,const std::string & packageName)1138 int32_t InputMethodSystemAbility::OnPackageRemoved(int32_t userId, const std::string &packageName)
1139 {
1140 FullImeInfoManager::GetInstance().Delete(userId, packageName);
1141 // if the app that doesn't belong to current user is removed, ignore it
1142 if (userId != userId_) {
1143 IMSA_HILOGD("userId: %{public}d, currentUserId: %{public}d.", userId, userId_);
1144 return ErrorCode::NO_ERROR;
1145 }
1146 auto currentImeBundle = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName;
1147 if (packageName == currentImeBundle) {
1148 // Switch to the default ime
1149 IMSA_HILOGI("user[%{public}d] ime: %{public}s is uninstalled.", userId, packageName.c_str());
1150 auto info = ImeInfoInquirer::GetInstance().GetDefaultImeInfo(userId);
1151 if (info == nullptr) {
1152 return ErrorCode::ERROR_PERSIST_CONFIG;
1153 }
1154 int32_t ret = SwitchExtension(userId, info);
1155 IMSA_HILOGI("switch ret: %{public}d", ret);
1156 }
1157 return ErrorCode::NO_ERROR;
1158 }
1159
OnUserUnlocked(const Message * msg)1160 void InputMethodSystemAbility::OnUserUnlocked(const Message *msg)
1161 {
1162 if (msg == nullptr || msg->msgContent_ == nullptr) {
1163 IMSA_HILOGE("message is nullptr");
1164 return;
1165 }
1166 int32_t userId = 0;
1167 if (!ITypesUtil::Unmarshal(*msg->msgContent_, userId)) {
1168 IMSA_HILOGE("failed to read message");
1169 return;
1170 }
1171 IMSA_HILOGI("userId: %{public}d", userId);
1172 if (userId != userId_) {
1173 return;
1174 }
1175 auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1176 if (session == nullptr) {
1177 UserSessionManager::GetInstance().AddUserSession(userId_);
1178 }
1179 session = UserSessionManager::GetInstance().GetUserSession(userId_);
1180 if (session == nullptr) {
1181 IMSA_HILOGE("%{public}d session is nullptr!", userId_);
1182 return;
1183 }
1184 session->OnUserUnlocked();
1185 }
1186
OnDisplayOptionalInputMethod()1187 int32_t InputMethodSystemAbility::OnDisplayOptionalInputMethod()
1188 {
1189 IMSA_HILOGD("InputMethodSystemAbility::OnDisplayOptionalInputMethod start.");
1190 auto abilityManager = GetAbilityManagerService();
1191 if (abilityManager == nullptr) {
1192 IMSA_HILOGE("InputMethodSystemAbility::get ability manager failed");
1193 return ErrorCode::ERROR_EX_SERVICE_SPECIFIC;
1194 }
1195 AAFwk::Want want;
1196 want.SetAction(SELECT_DIALOG_ACTION);
1197 want.SetElementName(SELECT_DIALOG_HAP, SELECT_DIALOG_ABILITY);
1198 int32_t ret = abilityManager->StartAbility(want);
1199 if (ret != ErrorCode::NO_ERROR && ret != START_SERVICE_ABILITY_ACTIVATING) {
1200 IMSA_HILOGE("start InputMethod ability failed, err: %{public}d", ret);
1201 return ErrorCode::ERROR_EX_SERVICE_SPECIFIC;
1202 }
1203 IMSA_HILOGI("start InputMethod ability success.");
1204 return ErrorCode::NO_ERROR;
1205 }
1206
GetAbilityManagerService()1207 sptr<AAFwk::IAbilityManager> InputMethodSystemAbility::GetAbilityManagerService()
1208 {
1209 IMSA_HILOGD("InputMethodSystemAbility::GetAbilityManagerService start");
1210 auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
1211 if (systemAbilityManager == nullptr) {
1212 IMSA_HILOGE("SystemAbilityManager is nullptr.");
1213 return nullptr;
1214 }
1215
1216 auto abilityMsObj = systemAbilityManager->GetSystemAbility(ABILITY_MGR_SERVICE_ID);
1217 if (abilityMsObj == nullptr) {
1218 IMSA_HILOGE("Failed to get ability manager service.");
1219 return nullptr;
1220 }
1221
1222 return iface_cast<AAFwk::IAbilityManager>(abilityMsObj);
1223 }
1224
SwitchByCombinationKey(uint32_t state)1225 int32_t InputMethodSystemAbility::SwitchByCombinationKey(uint32_t state)
1226 {
1227 IMSA_HILOGD("InputMethodSystemAbility::SwitchByCombinationKey start.");
1228 auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1229 if (session == nullptr) {
1230 IMSA_HILOGE("%{public}d session is nullptr", userId_);
1231 return ErrorCode::ERROR_NULL_POINTER;
1232 }
1233 if (session->IsProxyImeEnable()) {
1234 IMSA_HILOGI("proxy enable, not switch.");
1235 return ErrorCode::NO_ERROR;
1236 }
1237 if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_MODE, state)) {
1238 IMSA_HILOGI("switch mode.");
1239 return SwitchMode();
1240 }
1241 if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_LANGUAGE, state)) {
1242 IMSA_HILOGI("switch language.");
1243 return SwitchLanguage();
1244 }
1245 bool isScreenLocked = false;
1246 #ifdef IMF_SCREENLOCK_MGR_ENABLE
1247 if (ScreenLock::ScreenLockManager::GetInstance()->IsScreenLocked()) {
1248 IMSA_HILOGI("isScreenLocked now.");
1249 isScreenLocked = true;
1250 }
1251 #endif
1252 if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_IME, state) && !isScreenLocked) {
1253 IMSA_HILOGI("switch ime.");
1254 DealSwitchRequest();
1255 return ErrorCode::NO_ERROR;
1256 }
1257 IMSA_HILOGE("keycode is undefined");
1258 return ErrorCode::ERROR_EX_UNSUPPORTED_OPERATION;
1259 }
1260
DealSecurityChange()1261 void InputMethodSystemAbility::DealSecurityChange()
1262 {
1263 {
1264 std::lock_guard<std::mutex> lock(modeChangeMutex_);
1265 if (isChangeHandling_) {
1266 IMSA_HILOGI("already has mode change task.");
1267 hasPendingChanges_ = true;
1268 return;
1269 } else {
1270 isChangeHandling_ = true;
1271 hasPendingChanges_ = true;
1272 }
1273 }
1274 auto changeTask = [this]() {
1275 pthread_setname_np(pthread_self(), "SecurityChange");
1276 auto checkChangeCount = [this]() {
1277 std::lock_guard<std::mutex> lock(modeChangeMutex_);
1278 if (hasPendingChanges_) {
1279 return true;
1280 }
1281 isChangeHandling_ = false;
1282 return false;
1283 };
1284 do {
1285 OnSecurityModeChange();
1286 } while (checkChangeCount());
1287 };
1288 std::thread(changeTask).detach();
1289 }
1290
DealSwitchRequest()1291 void InputMethodSystemAbility::DealSwitchRequest()
1292 {
1293 {
1294 std::lock_guard<std::mutex> lock(switchImeMutex_);
1295 // 0 means current swich ime task count.
1296 if (switchTaskExecuting_.load()) {
1297 IMSA_HILOGI("already has switch ime task.");
1298 ++targetSwitchCount_;
1299 return;
1300 } else {
1301 switchTaskExecuting_.store(true);
1302 ++targetSwitchCount_;
1303 }
1304 }
1305 auto switchTask = [this]() {
1306 auto checkSwitchCount = [this]() {
1307 std::lock_guard<std::mutex> lock(switchImeMutex_);
1308 if (targetSwitchCount_ > 0) {
1309 return true;
1310 }
1311 switchTaskExecuting_.store(false);
1312 return false;
1313 };
1314 do {
1315 SwitchType();
1316 } while (checkSwitchCount());
1317 };
1318 // 0 means delay time is 0.
1319 serviceHandler_->PostTask(switchTask, "SwitchImeTask", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
1320 }
1321
SwitchMode()1322 int32_t InputMethodSystemAbility::SwitchMode()
1323 {
1324 auto bundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
1325 auto subName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->subName;
1326 auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, bundleName, subName);
1327 if (info == nullptr) {
1328 IMSA_HILOGE("current ime is abnormal!");
1329 return ErrorCode::ERROR_BAD_PARAMETERS;
1330 }
1331 if (info->isNewIme) {
1332 IMSA_HILOGD("the switching operation is handed over to ime.");
1333 return ErrorCode::NO_ERROR;
1334 }
1335 auto condition = info->subProp.mode == "upper" ? Condition::LOWER : Condition::UPPER;
1336 auto target = ImeInfoInquirer::GetInstance().FindTargetSubtypeByCondition(info->subProps, condition);
1337 if (target == nullptr) {
1338 IMSA_HILOGE("target is empty!");
1339 return ErrorCode::ERROR_BAD_PARAMETERS;
1340 }
1341 SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id };
1342 auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1343 if (session == nullptr) {
1344 IMSA_HILOGE("%{public}d session is nullptr", userId_);
1345 return ErrorCode::ERROR_NULL_POINTER;
1346 }
1347 session->GetSwitchQueue().Push(switchInfo);
1348 return OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA);
1349 }
1350
SwitchLanguage()1351 int32_t InputMethodSystemAbility::SwitchLanguage()
1352 {
1353 auto bundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
1354 auto subName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->subName;
1355 auto info = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, bundleName, subName);
1356 if (info == nullptr) {
1357 IMSA_HILOGE("current ime is abnormal!");
1358 return ErrorCode::ERROR_BAD_PARAMETERS;
1359 }
1360 if (info->isNewIme) {
1361 IMSA_HILOGD("the switching operation is handed over to ime.");
1362 return ErrorCode::NO_ERROR;
1363 }
1364 if (info->subProp.language != "chinese" && info->subProp.language != "english") {
1365 return ErrorCode::NO_ERROR;
1366 }
1367 auto condition = info->subProp.language == "chinese" ? Condition::ENGLISH : Condition::CHINESE;
1368 auto target = ImeInfoInquirer::GetInstance().FindTargetSubtypeByCondition(info->subProps, condition);
1369 if (target == nullptr) {
1370 IMSA_HILOGE("target is empty!");
1371 return ErrorCode::ERROR_BAD_PARAMETERS;
1372 }
1373 SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id };
1374 auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1375 if (session == nullptr) {
1376 IMSA_HILOGE("%{public}d session is nullptr", userId_);
1377 return ErrorCode::ERROR_NULL_POINTER;
1378 }
1379 session->GetSwitchQueue().Push(switchInfo);
1380 return OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA);
1381 }
1382
SwitchType()1383 int32_t InputMethodSystemAbility::SwitchType()
1384 {
1385 SwitchInfo switchInfo = { std::chrono::system_clock::now(), "", "" };
1386 uint32_t cacheCount = 0;
1387 {
1388 std::lock_guard<std::mutex> lock(switchImeMutex_);
1389 cacheCount = targetSwitchCount_.exchange(0);
1390 }
1391 int32_t ret =
1392 ImeInfoInquirer::GetInstance().GetSwitchInfoBySwitchCount(switchInfo, userId_, enableImeOn_.load(), cacheCount);
1393 if (ret != ErrorCode::NO_ERROR) {
1394 IMSA_HILOGE("get next SwitchInfo failed, stop switching ime.");
1395 return ret;
1396 }
1397 IMSA_HILOGD("switch to: %{public}s.", switchInfo.bundleName.c_str());
1398 switchInfo.timestamp = std::chrono::system_clock::now();
1399 auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1400 if (session == nullptr) {
1401 IMSA_HILOGE("%{public}d session is nullptr", userId_);
1402 return ErrorCode::ERROR_NULL_POINTER;
1403 }
1404 session->GetSwitchQueue().Push(switchInfo);
1405 return OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA);
1406 }
1407
InitMonitors()1408 void InputMethodSystemAbility::InitMonitors()
1409 {
1410 int32_t ret = InitAccountMonitor();
1411 IMSA_HILOGI("init account monitor, ret: %{public}d.", ret);
1412 SubscribeCommonEvent();
1413 ret = InitMemMgrMonitor();
1414 IMSA_HILOGI("init MemMgr monitor, ret: %{public}d.", ret);
1415 ret = InitKeyEventMonitor();
1416 IMSA_HILOGI("init KeyEvent monitor, ret: %{public}d.", ret);
1417 ret = InitWmsMonitor();
1418 IMSA_HILOGI("init wms monitor, ret: %{public}d.", ret);
1419 InitSystemLanguageMonitor();
1420 }
1421
HandleDataShareReady()1422 void InputMethodSystemAbility::HandleDataShareReady()
1423 {
1424 if (ImeInfoInquirer::GetInstance().IsEnableInputMethod()) {
1425 IMSA_HILOGW("Enter enable mode.");
1426 RegisterEnableImeObserver();
1427 EnableImeDataParser::GetInstance()->Initialize(userId_);
1428 enableImeOn_.store(true);
1429 }
1430 if (ImeInfoInquirer::GetInstance().IsEnableSecurityMode()) {
1431 IMSA_HILOGW("Enter security mode.");
1432 RegisterSecurityModeObserver();
1433 SecurityModeParser::GetInstance()->Initialize(userId_);
1434 enableSecurityMode_.store(true);
1435 }
1436 FullImeInfoManager::GetInstance().Init();
1437 }
1438
InitAccountMonitor()1439 int32_t InputMethodSystemAbility::InitAccountMonitor()
1440 {
1441 IMSA_HILOGI("InputMethodSystemAbility::InitAccountMonitor start.");
1442 return ImCommonEventManager::GetInstance()->SubscribeAccountManagerService([this]() { HandleOsAccountStarted(); });
1443 }
1444
InitKeyEventMonitor()1445 int32_t InputMethodSystemAbility::InitKeyEventMonitor()
1446 {
1447 IMSA_HILOGI("InputMethodSystemAbility::InitKeyEventMonitor start.");
1448 bool ret = ImCommonEventManager::GetInstance()->SubscribeKeyboardEvent(
1449 [this](uint32_t keyCode) { return SwitchByCombinationKey(keyCode); });
1450 return ret ? ErrorCode::NO_ERROR : ErrorCode::ERROR_SERVICE_START_FAILED;
1451 }
1452
InitWmsMonitor()1453 bool InputMethodSystemAbility::InitWmsMonitor()
1454 {
1455 return ImCommonEventManager::GetInstance()->SubscribeWindowManagerService([this]() { HandleWmsStarted(); });
1456 }
1457
InitMemMgrMonitor()1458 bool InputMethodSystemAbility::InitMemMgrMonitor()
1459 {
1460 return ImCommonEventManager::GetInstance()->SubscribeMemMgrService([this]() { HandleMemStarted(); });
1461 }
1462
InitWmsConnectionMonitor()1463 void InputMethodSystemAbility::InitWmsConnectionMonitor()
1464 {
1465 WmsConnectionMonitorManager::GetInstance().RegisterWMSConnectionChangedListener(
1466 [this](bool isConnected, int32_t userId, int32_t screenId) {
1467 isConnected ? HandleWmsConnected(userId, screenId) : HandleWmsDisconnected(userId, screenId);
1468 });
1469 }
1470
InitSystemLanguageMonitor()1471 void InputMethodSystemAbility::InitSystemLanguageMonitor()
1472 {
1473 SystemLanguageObserver::GetInstance().Watch();
1474 }
1475
InitFocusChangedMonitor()1476 void InputMethodSystemAbility::InitFocusChangedMonitor()
1477 {
1478 FocusMonitorManager::GetInstance().RegisterFocusChangedListener(
1479 [this](bool isOnFocused, int32_t pid, int32_t uid) { HandleFocusChanged(isOnFocused, pid, uid); });
1480 }
1481
RegisterEnableImeObserver()1482 void InputMethodSystemAbility::RegisterEnableImeObserver()
1483 {
1484 int32_t ret = SettingsDataUtils::GetInstance()->CreateAndRegisterObserver(EnableImeDataParser::ENABLE_IME,
1485 [this]() { DatashareCallback(EnableImeDataParser::ENABLE_IME); });
1486 IMSA_HILOGI("register enable ime observer, ret: %{public}d.", ret);
1487 ret = SettingsDataUtils::GetInstance()->CreateAndRegisterObserver(EnableImeDataParser::ENABLE_KEYBOARD,
1488 [this]() { DatashareCallback(EnableImeDataParser::ENABLE_KEYBOARD); });
1489 IMSA_HILOGI("register enable keyboard observer, ret: %{public}d.", ret);
1490 }
1491
RegisterSecurityModeObserver()1492 void InputMethodSystemAbility::RegisterSecurityModeObserver()
1493 {
1494 int32_t ret = SettingsDataUtils::GetInstance()->CreateAndRegisterObserver(SecurityModeParser::SECURITY_MODE,
1495 [this]() { DatashareCallback(SecurityModeParser::SECURITY_MODE); });
1496 IMSA_HILOGI("register security mode observer, ret: %{public}d", ret);
1497 }
1498
DatashareCallback(const std::string & key)1499 void InputMethodSystemAbility::DatashareCallback(const std::string &key)
1500 {
1501 IMSA_HILOGI("start.");
1502 if (key == EnableImeDataParser::ENABLE_KEYBOARD || key == EnableImeDataParser::ENABLE_IME) {
1503 EnableImeDataParser::GetInstance()->OnConfigChanged(userId_, key);
1504 std::lock_guard<std::mutex> autoLock(checkMutex_);
1505 SwitchInfo switchInfo;
1506 if (EnableImeDataParser::GetInstance()->CheckNeedSwitch(key, switchInfo, userId_)) {
1507 auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1508 if (session == nullptr) {
1509 IMSA_HILOGE("%{public}d session is nullptr", userId_);
1510 return;
1511 }
1512 switchInfo.timestamp = std::chrono::system_clock::now();
1513 session->GetSwitchQueue().Push(switchInfo);
1514 OnSwitchInputMethod(userId_, switchInfo, SwitchTrigger::IMSA);
1515 }
1516 }
1517 if (key == SecurityModeParser::SECURITY_MODE) {
1518 DealSecurityChange();
1519 }
1520 }
1521
OnSecurityModeChange()1522 void InputMethodSystemAbility::OnSecurityModeChange()
1523 {
1524 {
1525 std::lock_guard<std::mutex> lock(modeChangeMutex_);
1526 hasPendingChanges_ = false;
1527 }
1528 auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
1529 auto oldMode = SecurityModeParser::GetInstance()->GetSecurityMode(currentIme->bundleName, userId_);
1530 SecurityModeParser::GetInstance()->UpdateFullModeList(userId_);
1531 auto newMode = SecurityModeParser::GetInstance()->GetSecurityMode(currentIme->bundleName, userId_);
1532 if (oldMode == newMode) {
1533 IMSA_HILOGD("current ime mode not changed.");
1534 return;
1535 }
1536 IMSA_HILOGI("ime: %{public}s securityMode change to: %{public}d.", currentIme->bundleName.c_str(),
1537 static_cast<int32_t>(newMode));
1538 auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1539 if (session == nullptr) {
1540 IMSA_HILOGE("%{public}d session is nullptr", userId_);
1541 return;
1542 }
1543 session->OnSecurityChange(static_cast<int32_t>(newMode));
1544 session->AddRestartIme();
1545 }
1546
GetSecurityMode(int32_t & security)1547 int32_t InputMethodSystemAbility::GetSecurityMode(int32_t &security)
1548 {
1549 IMSA_HILOGD("InputMethodSystemAbility start.");
1550 if (!enableSecurityMode_.load()) {
1551 security = static_cast<int32_t>(SecurityMode::FULL);
1552 return ErrorCode::NO_ERROR;
1553 }
1554 auto userId = GetCallingUserId();
1555 auto bundleName = FullImeInfoManager::GetInstance().Get(userId, IPCSkeleton::GetCallingTokenID());
1556 if (bundleName.empty()) {
1557 bundleName = identityChecker_->GetBundleNameByToken(IPCSkeleton::GetCallingTokenID());
1558 IMSA_HILOGW("%{public}s tokenId not find.", bundleName.c_str());
1559 }
1560 SecurityMode mode = SecurityModeParser::GetInstance()->GetSecurityMode(bundleName, userId);
1561 security = static_cast<int32_t>(mode);
1562 return ErrorCode::NO_ERROR;
1563 }
1564
UnRegisteredProxyIme(UnRegisteredType type,const sptr<IInputMethodCore> & core)1565 int32_t InputMethodSystemAbility::UnRegisteredProxyIme(UnRegisteredType type, const sptr<IInputMethodCore> &core)
1566 {
1567 if (!identityChecker_->IsNativeSa(IPCSkeleton::GetCallingTokenID())) {
1568 IMSA_HILOGE("not native sa!");
1569 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1570 }
1571 auto userId = GetCallingUserId();
1572 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1573 if (session == nullptr) {
1574 IMSA_HILOGE("%{public}d session is nullptr", userId);
1575 return ErrorCode::ERROR_NULL_POINTER;
1576 }
1577 if (type == UnRegisteredType::SWITCH_PROXY_IME_TO_IME) {
1578 int32_t ret = ErrorCode::NO_ERROR;
1579 if (session->CheckSecurityMode()) {
1580 ret = StartInputType(userId, InputType::SECURITY_INPUT);
1581 } else {
1582 ret = session->RestoreCurrentIme();
1583 }
1584 if (ret != ErrorCode::NO_ERROR) {
1585 return ret;
1586 }
1587 }
1588 return session->OnUnRegisteredProxyIme(type, core);
1589 }
1590
CheckEnableAndSwitchPermission()1591 int32_t InputMethodSystemAbility::CheckEnableAndSwitchPermission()
1592 {
1593 if (!identityChecker_->IsNativeSa(IPCSkeleton::GetCallingFullTokenID())) {
1594 IMSA_HILOGE("not native sa!");
1595 return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
1596 }
1597 if (!identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)) {
1598 IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY!");
1599 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1600 }
1601 return ErrorCode::NO_ERROR;
1602 }
1603
CheckSwitchPermission(int32_t userId,const SwitchInfo & switchInfo,SwitchTrigger trigger)1604 int32_t InputMethodSystemAbility::CheckSwitchPermission(int32_t userId, const SwitchInfo &switchInfo,
1605 SwitchTrigger trigger)
1606 {
1607 IMSA_HILOGD("trigger: %{public}d.", static_cast<int32_t>(trigger));
1608 if (trigger == SwitchTrigger::IMSA) {
1609 return ErrorCode::NO_ERROR;
1610 }
1611 if (trigger == SwitchTrigger::NATIVE_SA) {
1612 return CheckEnableAndSwitchPermission();
1613 }
1614 if (trigger == SwitchTrigger::SYSTEM_APP) {
1615 if (!identityChecker_->IsSystemApp(IPCSkeleton::GetCallingFullTokenID())) {
1616 IMSA_HILOGE("not system app!");
1617 return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
1618 }
1619 if (!identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)) {
1620 IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY");
1621 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1622 }
1623 return ErrorCode::NO_ERROR;
1624 }
1625 if (trigger == SwitchTrigger::CURRENT_IME) {
1626 // PERMISSION_CONNECT_IME_ABILITY check temporarily reserved for application adaptation, will be deleted soon
1627 if (identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)) {
1628 return ErrorCode::NO_ERROR;
1629 }
1630 IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY");
1631 // switchInfo.subName.empty() check temporarily reserved for application adaptation, will be deleted soon
1632 auto currentBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName;
1633 if (identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), currentBundleName) &&
1634 !switchInfo.subName.empty()) {
1635 return ErrorCode::NO_ERROR;
1636 }
1637 IMSA_HILOGE("not current ime!");
1638 /* return ErrorCode::ERROR_STATUS_PERMISSION_DENIED temporarily reserved for application adaptation,
1639 will be replaced by ERROR_NOT_CURRENT_IME soon */
1640 return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
1641 }
1642 return ErrorCode::ERROR_BAD_PARAMETERS;
1643 }
1644
IsStartInputTypePermitted(int32_t userId)1645 bool InputMethodSystemAbility::IsStartInputTypePermitted(int32_t userId)
1646 {
1647 auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultImeInfo(userId);
1648 if (defaultIme == nullptr) {
1649 IMSA_HILOGE("failed to get default ime!");
1650 return false;
1651 }
1652 auto tokenId = IPCSkeleton::GetCallingTokenID();
1653 if (identityChecker_->IsBundleNameValid(tokenId, defaultIme->prop.name)) {
1654 return true;
1655 }
1656 if (identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
1657 return true;
1658 }
1659 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1660 if (session == nullptr) {
1661 IMSA_HILOGE("%{public}d session is nullptr", userId);
1662 return false;
1663 }
1664 return identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), tokenId) && session->IsBoundToClient();
1665 }
1666
ConnectSystemCmd(const sptr<IRemoteObject> & channel,sptr<IRemoteObject> & agent)1667 int32_t InputMethodSystemAbility::ConnectSystemCmd(const sptr<IRemoteObject> &channel, sptr<IRemoteObject> &agent)
1668 {
1669 auto tokenId = IPCSkeleton::GetCallingTokenID();
1670 if (!identityChecker_->HasPermission(tokenId, PERMISSION_CONNECT_IME_ABILITY)) {
1671 IMSA_HILOGE("have not PERMISSION_CONNECT_IME_ABILITY");
1672 return ErrorCode::ERROR_STATUS_SYSTEM_PERMISSION;
1673 }
1674 auto userId = GetCallingUserId();
1675 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1676 if (session == nullptr) {
1677 IMSA_HILOGE("%{public}d session is nullptr", userId);
1678 return ErrorCode::ERROR_NULL_POINTER;
1679 }
1680 return session->OnConnectSystemCmd(channel, agent);
1681 }
1682
HandleWmsConnected(int32_t userId,int32_t screenId)1683 void InputMethodSystemAbility::HandleWmsConnected(int32_t userId, int32_t screenId)
1684 {
1685 if (userId == userId_) {
1686 // device boot or scb in foreground reboot
1687 HandleScbStarted(userId, screenId);
1688 return;
1689 }
1690 // user switched
1691 HandleUserSwitched(userId);
1692 }
1693
HandleScbStarted(int32_t userId,int32_t screenId)1694 void InputMethodSystemAbility::HandleScbStarted(int32_t userId, int32_t screenId)
1695 {
1696 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1697 if (session == nullptr) {
1698 UserSessionManager::GetInstance().AddUserSession(userId);
1699 }
1700 session = UserSessionManager::GetInstance().GetUserSession(userId);
1701 if (session == nullptr) {
1702 IMSA_HILOGE("%{public}d session is nullptr", userId);
1703 return;
1704 }
1705 session->AddRestartIme();
1706 }
1707
HandleUserSwitched(int32_t userId)1708 void InputMethodSystemAbility::HandleUserSwitched(int32_t userId)
1709 {
1710 UpdateUserInfo(userId);
1711 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1712 if (session == nullptr) {
1713 UserSessionManager::GetInstance().AddUserSession(userId);
1714 }
1715 session = UserSessionManager::GetInstance().GetUserSession(userId);
1716 if (session == nullptr) {
1717 IMSA_HILOGE("%{public}d session is nullptr", userId);
1718 return;
1719 }
1720 auto imeData = session->GetReadyImeData(ImeType::IME);
1721 if (imeData == nullptr && session->IsWmsReady()) {
1722 session->StartCurrentIme();
1723 }
1724 }
1725
HandleWmsDisconnected(int32_t userId,int32_t screenId)1726 void InputMethodSystemAbility::HandleWmsDisconnected(int32_t userId, int32_t screenId)
1727 {
1728 // clear client
1729 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1730 if (session != nullptr) {
1731 session->RemoveCurrentClient();
1732 }
1733
1734 if (userId == userId_) {
1735 // user switched or scb in foreground died, not deal
1736 return;
1737 }
1738 // scb in background died, stop ime
1739 if (session == nullptr) {
1740 return;
1741 }
1742 session->StopCurrentIme();
1743 }
1744
HandleWmsStarted()1745 void InputMethodSystemAbility::HandleWmsStarted()
1746 {
1747 // singleton, device boot, wms reboot
1748 IMSA_HILOGI("Wms start.");
1749 InitFocusChangedMonitor();
1750 if (isScbEnable_.load()) {
1751 IMSA_HILOGI("scb enable, register WMS connection listener.");
1752 InitWmsConnectionMonitor();
1753 return;
1754 }
1755 // clear client
1756 auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1757 if (session != nullptr) {
1758 session->RemoveCurrentClient();
1759 }
1760 if (session == nullptr) {
1761 UserSessionManager::GetInstance().AddUserSession(userId_);
1762 }
1763 session = UserSessionManager::GetInstance().GetUserSession(userId_);
1764 if (session == nullptr) {
1765 IMSA_HILOGE("%{public}d session is nullptr", userId_);
1766 return;
1767 }
1768 session->AddRestartIme();
1769 StopImeInBackground();
1770 }
1771
HandleFocusChanged(bool isFocused,int32_t pid,int32_t uid)1772 void InputMethodSystemAbility::HandleFocusChanged(bool isFocused, int32_t pid, int32_t uid)
1773 {
1774 int32_t userId = GetUserId(uid);
1775 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1776 if (session == nullptr) {
1777 IMSA_HILOGE("[%{public}d, %{public}d] session is nullptr", uid, userId);
1778 return;
1779 }
1780 isFocused ? session->OnFocused(pid, uid) : session->OnUnfocused(pid, uid);
1781 }
1782
HandleMemStarted()1783 void InputMethodSystemAbility::HandleMemStarted()
1784 {
1785 // singleton
1786 IMSA_HILOGI("MemMgr start.");
1787 Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 1, INPUT_METHOD_SYSTEM_ABILITY_ID);
1788 auto session = UserSessionManager::GetInstance().GetUserSession(userId_);
1789 if (session == nullptr) {
1790 UserSessionManager::GetInstance().AddUserSession(userId_);
1791 }
1792 session = UserSessionManager::GetInstance().GetUserSession(userId_);
1793 if (session == nullptr) {
1794 IMSA_HILOGE("%{public}d session is nullptr", userId_);
1795 return;
1796 }
1797 session->AddRestartIme();
1798 StopImeInBackground();
1799 }
1800
HandleOsAccountStarted()1801 void InputMethodSystemAbility::HandleOsAccountStarted()
1802 {
1803 IMSA_HILOGI("account start");
1804 auto userId = OsAccountAdapter::GetForegroundOsAccountLocalId();
1805 if (userId_ != userId) {
1806 UpdateUserInfo(userId);
1807 } else {
1808 UpdateUserLockState();
1809 }
1810 Message *msg = new (std::nothrow) Message(MessageID::MSG_ID_OS_ACCOUNT_STARTED, nullptr);
1811 if (msg == nullptr) {
1812 return;
1813 }
1814 MessageHandler::Instance()->SendMessage(msg);
1815 }
1816
StopImeInBackground()1817 void InputMethodSystemAbility::StopImeInBackground()
1818 {
1819 auto task = [this]() {
1820 auto sessions = UserSessionManager::GetInstance().GetUserSessions();
1821 for (const auto &tempSession : sessions) {
1822 if (tempSession.first != userId_) {
1823 tempSession.second->StopCurrentIme();
1824 }
1825 }
1826 };
1827 serviceHandler_->PostTask(task, "StopImeInBackground", 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
1828 }
1829
GetUserId(int32_t uid)1830 int32_t InputMethodSystemAbility::GetUserId(int32_t uid)
1831 {
1832 IMSA_HILOGD("uid:%{public}d", uid);
1833 auto userId = OsAccountAdapter::GetOsAccountLocalIdFromUid(uid);
1834 // 0 represents user 0 in the system
1835 if (userId == 0) {
1836 IMSA_HILOGI("user 0");
1837 return userId_;
1838 }
1839 return userId;
1840 }
1841
GetCallingUserId()1842 int32_t InputMethodSystemAbility::GetCallingUserId()
1843 {
1844 auto uid = IPCSkeleton::GetCallingUid();
1845 return GetUserId(uid);
1846 }
1847
IsCurrentIme(int32_t userId)1848 bool InputMethodSystemAbility::IsCurrentIme(int32_t userId)
1849 {
1850 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1851 if (session == nullptr) {
1852 IMSA_HILOGE("%{public}d session is nullptr", userId);
1853 return false;
1854 }
1855 auto bundleName = FullImeInfoManager::GetInstance().Get(userId, IPCSkeleton::GetCallingTokenID());
1856 if (bundleName.empty()) {
1857 IMSA_HILOGW("user:%{public}d tokenId:%{public}d not find.", userId, IPCSkeleton::GetCallingTokenID());
1858 bundleName = identityChecker_->GetBundleNameByToken(IPCSkeleton::GetCallingTokenID());
1859 }
1860 auto imeData = session->GetImeData(ImeType::IME);
1861 return imeData != nullptr && bundleName == imeData->ime.first;
1862 }
1863
StartInputType(int32_t userId,InputType type)1864 int32_t InputMethodSystemAbility::StartInputType(int32_t userId, InputType type)
1865 {
1866 auto session = UserSessionManager::GetInstance().GetUserSession(userId);
1867 if (session == nullptr) {
1868 IMSA_HILOGE("%{public}d session is nullptr", userId);
1869 return ErrorCode::ERROR_NULL_POINTER;
1870 }
1871 ImeIdentification ime;
1872 int32_t ret = InputTypeManager::GetInstance().GetImeByInputType(type, ime);
1873 if (ret != ErrorCode::NO_ERROR) {
1874 IMSA_HILOGW("not find input type: %{public}d.", type);
1875 // add for not adapter for SECURITY_INPUT
1876 if (type == InputType::SECURITY_INPUT) {
1877 return session->RestoreCurrentIme();
1878 }
1879 return ret;
1880 }
1881 SwitchInfo switchInfo = { std::chrono::system_clock::now(), ime.bundleName, ime.subName };
1882 session->GetSwitchQueue().Push(switchInfo);
1883 IMSA_HILOGI("start input type: %{public}d.", type);
1884 return type == InputType::SECURITY_INPUT ? OnStartInputType(userId, switchInfo, false)
1885 : OnStartInputType(userId, switchInfo, true);
1886 }
1887
NeedHideWhenSwitchInputType(int32_t userId,bool & needHide)1888 void InputMethodSystemAbility::NeedHideWhenSwitchInputType(int32_t userId, bool &needHide)
1889 {
1890 ImeIdentification ime;
1891 InputTypeManager::GetInstance().GetImeByInputType(InputType::SECURITY_INPUT, ime);
1892 auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
1893 if (currentImeCfg == nullptr) {
1894 IMSA_HILOGI("currentImeCfg is nullptr");
1895 return;
1896 }
1897 needHide = currentImeCfg->bundleName == ime.bundleName;
1898 }
1899 } // namespace MiscServices
1900 } // namespace OHOS