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