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