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