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