1 /*
2  * Copyright (c) 2023 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 "ime_info_inquirer.h"
17 
18 #include <algorithm>
19 #include <string>
20 
21 #include "app_mgr_client.h"
22 #include "application_info.h"
23 #include "bundle_mgr_client_impl.h"
24 #include "file_operator.h"
25 #include "full_ime_info_manager.h"
26 #include "global.h"
27 #include "if_system_ability_manager.h"
28 #include "ime_cfg_manager.h"
29 #include "input_method_info.h"
30 #include "input_type_manager.h"
31 #include "iservice_registry.h"
32 #include "locale_config.h"
33 #include "locale_info.h"
34 #include "os_account_adapter.h"
35 #include "parameter.h"
36 #include "running_process_info.h"
37 #include "string_ex.h"
38 #include "system_ability.h"
39 #include "system_ability_definition.h"
40 
41 namespace OHOS {
42 namespace MiscServices {
43 namespace {
44 using namespace OHOS::AppExecFwk;
45 using namespace Global::Resource;
46 using namespace OHOS::AAFwk;
47 constexpr const char *SUBTYPE_PROFILE_METADATA_NAME = "ohos.extension.input_method";
48 constexpr const char *TEMPORARY_INPUT_METHOD_METADATA_NAME = "ohos.extension.temporary_input_method";
49 constexpr uint32_t SUBTYPE_PROFILE_NUM = 1;
50 constexpr const char *DEFAULT_IME_KEY = "persist.sys.default_ime";
51 constexpr int32_t CONFIG_LEN = 128;
52 constexpr uint32_t DEFAULT_BMS_VALUE = 0;
53 } // namespace
GetInstance()54 ImeInfoInquirer &ImeInfoInquirer::GetInstance()
55 {
56     static ImeInfoInquirer instance;
57     return instance;
58 }
59 
InitSystemConfig()60 void ImeInfoInquirer::InitSystemConfig()
61 {
62     auto ret = SysCfgParser::ParseSystemConfig(systemConfig_);
63     if (!ret) {
64         IMSA_HILOGE("parse systemConfig failed");
65         return;
66     }
67 }
68 
IsEnableInputMethod()69 bool ImeInfoInquirer::IsEnableInputMethod()
70 {
71     return systemConfig_.enableInputMethodFeature;
72 }
73 
IsEnableSecurityMode()74 bool ImeInfoInquirer::IsEnableSecurityMode()
75 {
76     return systemConfig_.enableFullExperienceFeature;
77 }
78 
QueryImeExtInfos(const int32_t userId,std::vector<ExtensionAbilityInfo> & infos)79 bool ImeInfoInquirer::QueryImeExtInfos(const int32_t userId, std::vector<ExtensionAbilityInfo> &infos)
80 {
81     IMSA_HILOGD("userId: %{public}d.", userId);
82     auto bundleMgr = GetBundleMgr();
83     if (bundleMgr == nullptr) {
84         IMSA_HILOGE("failed to GetBundleMgr");
85         return false;
86     }
87     if (!bundleMgr->QueryExtensionAbilityInfos(ExtensionAbilityType::INPUTMETHOD, userId, infos)) {
88         IMSA_HILOGF("query extension infos failed from bundleMgr!");
89         return false;
90     }
91     return true;
92 }
93 
GetExtInfosByBundleName(const int32_t userId,const std::string & bundleName,std::vector<AppExecFwk::ExtensionAbilityInfo> & extInfos)94 int32_t ImeInfoInquirer::GetExtInfosByBundleName(
95     const int32_t userId, const std::string &bundleName, std::vector<AppExecFwk::ExtensionAbilityInfo> &extInfos)
96 {
97     IMSA_HILOGD("userId: %{public}d, bundleName: %{public}s.", userId, bundleName.c_str());
98     std::vector<AppExecFwk::ExtensionAbilityInfo> tempExtInfos;
99     if (!QueryImeExtInfos(userId, tempExtInfos)) {
100         IMSA_HILOGE("failed to QueryImeExtInfos!");
101         return ErrorCode::ERROR_BAD_PARAMETERS;
102     }
103     for (const auto &extInfo : tempExtInfos) {
104         if (extInfo.bundleName == bundleName) {
105             extInfos.emplace_back(extInfo);
106         }
107     }
108     if (extInfos.empty()) {
109         IMSA_HILOGE("bundleName: %{public}s extInfos is empty!", bundleName.c_str());
110         return ErrorCode::ERROR_BAD_PARAMETERS;
111     }
112     return ErrorCode::NO_ERROR;
113 }
114 
GetImeInfo(int32_t userId,const std::string & bundleName,const std::string & subName)115 std::shared_ptr<ImeInfo> ImeInfoInquirer::GetImeInfo(int32_t userId, const std::string &bundleName,
116     const std::string &subName)
117 {
118     IMSA_HILOGD("userId: %{public}d, bundleName: %{public}s, subName: %{public}s.", userId, bundleName.c_str(),
119         subName.c_str());
120     auto info = GetImeInfoFromCache(userId, bundleName, subName);
121     return info == nullptr ? GetImeInfoFromBundleMgr(userId, bundleName, subName) : info;
122 }
123 
GetImeInfoFromCache(const int32_t userId,const std::string & bundleName,const std::string & subName)124 std::shared_ptr<ImeInfo> ImeInfoInquirer::GetImeInfoFromCache(const int32_t userId, const std::string &bundleName,
125     const std::string &subName)
126 {
127     auto fullInfo = FullImeInfoManager::GetInstance().Get(userId);
128     auto it = std::find_if(fullInfo.begin(), fullInfo.end(),
129         [&bundleName](const FullImeInfo &info) { return info.prop.name == bundleName; });
130     if (it == fullInfo.end()) {
131         return nullptr;
132     }
133     auto info = std::make_shared<ImeInfo>();
134     auto subProps = it->subProps;
135     info->isSpecificSubName = !subName.empty();
136     if (subName.empty() && !subProps.empty()) {
137         info->subProp = subProps[0];
138     } else {
139         auto iter = std::find_if(subProps.begin(), subProps.end(),
140             [&subName](const SubProperty &subProp) { return subProp.id == subName; });
141         if (iter == subProps.end()) {
142             IMSA_HILOGE("find subName: %{public}s failed", subName.c_str());
143             return nullptr;
144         }
145         info->subProp = *iter;
146     }
147     info->isNewIme = it->isNewIme;
148     info->subProps = it->subProps;
149     info->prop = it->prop;
150     if (!info->isNewIme) {
151         // old ime, make the id of prop same with the id of subProp.
152         info->prop.id = info->subProp.id;
153     }
154     return info;
155 }
156 
GetImeInfoFromBundleMgr(const int32_t userId,const std::string & bundleName,const std::string & subName)157 std::shared_ptr<ImeInfo> ImeInfoInquirer::GetImeInfoFromBundleMgr(
158     const int32_t userId, const std::string &bundleName, const std::string &subName)
159 {
160     IMSA_HILOGD("userId: %{public}d, bundleName: %{public}s, subName: %{public}s.", userId, bundleName.c_str(),
161         subName.c_str());
162     std::vector<AppExecFwk::ExtensionAbilityInfo> extInfos;
163     auto ret = ImeInfoInquirer::GetInstance().GetExtInfosByBundleName(userId, bundleName, extInfos);
164     if (ret != ErrorCode::NO_ERROR || extInfos.empty()) {
165         IMSA_HILOGE("userId: %{public}d getExtInfosByBundleName %{public}s failed!", userId, bundleName.c_str());
166         return nullptr;
167     }
168     auto info = std::make_shared<ImeInfo>();
169     info->prop.name = extInfos[0].bundleName;
170     info->prop.id = extInfos[0].name;
171     info->prop.label = GetTargetString(extInfos[0], ImeTargetString::LABEL, userId);
172     info->prop.labelId = extInfos[0].applicationInfo.labelId;
173     info->prop.iconId = extInfos[0].applicationInfo.iconId;
174 
175     std::vector<SubProperty> subProps;
176     info->isNewIme = IsNewExtInfos(extInfos);
177     ret = info->isNewIme ? ListInputMethodSubtype(userId, extInfos[0], subProps)
178                          : ListInputMethodSubtype(userId, extInfos, subProps);
179     if (ret != ErrorCode::NO_ERROR || subProps.empty()) {
180         IMSA_HILOGE("userId: %{public}d listInputMethodSubtype failed!", userId);
181         return nullptr;
182     }
183     info->subProps = subProps;
184     if (subName.empty()) {
185         info->isSpecificSubName = false;
186         info->subProp = subProps[0];
187     } else {
188         auto it = std::find_if(subProps.begin(), subProps.end(),
189             [&subName](const SubProperty &subProp) { return subProp.id == subName; });
190         if (it == subProps.end()) {
191             IMSA_HILOGE("find subName: %{public}s failed", subName.c_str());
192             return nullptr;
193         }
194         info->subProp = *it;
195     }
196     // old ime, make the id of prop same with the id of subProp.
197     if (!info->isNewIme) {
198         info->prop.id = info->subProp.id;
199     }
200     return info;
201 }
202 
GetDumpInfo(int32_t userId)203 std::string ImeInfoInquirer::GetDumpInfo(int32_t userId)
204 {
205     auto properties = ListInputMethodInfo(userId);
206     if (properties.empty()) {
207         return "";
208     }
209     auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
210     bool isBegin = true;
211     std::string params = "{\"imeList\":[";
212     for (const auto &property : properties) {
213         params += isBegin ? "" : "},";
214         isBegin = false;
215 
216         std::string imeId = property.mPackageName + "/" + property.mAbilityName;
217         params += "{\"ime\": \"" + imeId + "\",";
218         params += "\"labelId\": \"" + std::to_string(property.labelId) + "\",";
219         params += "\"descriptionId\": \"" + std::to_string(property.descriptionId) + "\",";
220         std::string isCurrentIme = currentImeCfg->imeId == imeId ? "true" : "false";
221         params += "\"isCurrentIme\": \"" + isCurrentIme + "\",";
222         params += "\"label\": \"" + property.label + "\",";
223         params += "\"description\": \"" + property.description + "\"";
224     }
225     params += "}]}";
226     return params;
227 }
228 
ListInputMethodInfo(const int32_t userId)229 std::vector<InputMethodInfo> ImeInfoInquirer::ListInputMethodInfo(const int32_t userId)
230 {
231     IMSA_HILOGD("userId: %{public}d.", userId);
232     std::vector<ExtensionAbilityInfo> extensionInfos;
233     if (!QueryImeExtInfos(userId, extensionInfos)) {
234         IMSA_HILOGE("userId: %{public}d queryImeExtInfos failed!", userId);
235         return {};
236     }
237     std::vector<InputMethodInfo> properties;
238     for (const auto &extension : extensionInfos) {
239         auto applicationInfo = extension.applicationInfo;
240         auto label = GetTargetString(extension, ImeTargetString::LABEL, userId);
241         auto description = GetTargetString(extension, ImeTargetString::DESCRIPTION, userId);
242         InputMethodInfo property;
243         property.mPackageName = extension.bundleName;
244         property.mAbilityName = extension.name;
245         property.labelId = applicationInfo.labelId;
246         property.descriptionId = applicationInfo.descriptionId;
247         property.label = label;
248         property.description = description;
249         properties.emplace_back(property);
250     }
251     return properties;
252 }
253 
ListInputMethod(int32_t userId,InputMethodStatus status,std::vector<Property> & props,bool enableOn)254 int32_t ImeInfoInquirer::ListInputMethod(
255     int32_t userId, InputMethodStatus status, std::vector<Property> &props, bool enableOn)
256 {
257     IMSA_HILOGD("userId: %{public}d, status: %{public}d.", userId, status);
258     if (status == InputMethodStatus::ALL) {
259         return ListInputMethod(userId, props);
260     }
261     if (status == InputMethodStatus::ENABLE) {
262         return ListEnabledInputMethod(userId, props, enableOn);
263     }
264     if (status == InputMethodStatus::DISABLE) {
265         return ListDisabledInputMethod(userId, props, enableOn);
266     }
267     return ErrorCode::ERROR_BAD_PARAMETERS;
268 }
269 
ListInputMethod(const int32_t userId,std::vector<Property> & props)270 int32_t ImeInfoInquirer::ListInputMethod(const int32_t userId, std::vector<Property> &props)
271 {
272     IMSA_HILOGD("userId: %{public}d.", userId);
273     auto infos = FullImeInfoManager::GetInstance().Get(userId);
274     for (const auto &info : infos) {
275         props.push_back(info.prop);
276     }
277     if (!props.empty()) {
278         return ErrorCode::NO_ERROR;
279     }
280 
281     IMSA_HILOGD("%{public}d get all prop form bms.", userId);
282     std::vector<ExtensionAbilityInfo> extensionInfos;
283     if (!QueryImeExtInfos(userId, extensionInfos)) {
284         IMSA_HILOGE("failed to QueryImeExtInfos!");
285         return ErrorCode::ERROR_BAD_PARAMETERS;
286     }
287     for (const auto &extension : extensionInfos) {
288         auto it = std::find_if(props.begin(), props.end(),
289             [&extension](const Property &prop) { return prop.name == extension.bundleName; });
290         if (it != props.end()) {
291             continue;
292         }
293         if (IsTempInputMethod(extension)) {
294             continue;
295         }
296         props.push_back({ .name = extension.bundleName,
297             .id = extension.name,
298             .label = GetTargetString(extension, ImeTargetString::LABEL, userId),
299             .labelId = extension.applicationInfo.labelId,
300             .iconId = extension.applicationInfo.iconId });
301     }
302     return ErrorCode::NO_ERROR;
303 }
304 
ListEnabledInputMethod(const int32_t userId,std::vector<Property> & props,bool enableOn)305 int32_t ImeInfoInquirer::ListEnabledInputMethod(const int32_t userId, std::vector<Property> &props, bool enableOn)
306 {
307     IMSA_HILOGD("userId: %{public}d.", userId);
308     int32_t ret = ListInputMethod(userId, props);
309     if (ret != ErrorCode::NO_ERROR) {
310         IMSA_HILOGE("userId: %{public}d listInputMethod failed!", userId);
311         return ret;
312     }
313     if (enableOn) {
314         IMSA_HILOGD("enable on.");
315         std::vector<std::string> enableVec;
316         ret = EnableImeDataParser::GetInstance()->GetEnableIme(userId, enableVec);
317         if (ret != ErrorCode::NO_ERROR) {
318             IMSA_HILOGE("get enable data failed");
319             return ret;
320         }
321         auto info = GetDefaultIme();
322         enableVec.insert(enableVec.begin(), info.bundleName);
323 
324         auto newEnd = std::remove_if(props.begin(), props.end(), [&enableVec](const auto &prop) {
325             return std::find(enableVec.begin(), enableVec.end(), prop.name) == enableVec.end();
326         });
327         props.erase(newEnd, props.end());
328     }
329     return ErrorCode::NO_ERROR;
330 }
331 
ListDisabledInputMethod(const int32_t userId,std::vector<Property> & props,bool enableOn)332 int32_t ImeInfoInquirer::ListDisabledInputMethod(const int32_t userId, std::vector<Property> &props, bool enableOn)
333 {
334     IMSA_HILOGD("userId: %{public}d.", userId);
335     if (!enableOn) {
336         IMSA_HILOGD("enable mode off, get disabled ime.");
337         return ErrorCode::NO_ERROR;
338     }
339 
340     auto ret = ListInputMethod(userId, props);
341     if (ret != ErrorCode::NO_ERROR) {
342         IMSA_HILOGE("userId: %{public}d listInputMethod failed!", userId);
343         return ret;
344     }
345 
346     std::vector<std::string> enableVec;
347     ret = EnableImeDataParser::GetInstance()->GetEnableIme(userId, enableVec);
348     if (ret != ErrorCode::NO_ERROR) {
349         IMSA_HILOGE("get enable data failed");
350         return ret;
351     }
352     auto info = GetDefaultIme();
353     enableVec.insert(enableVec.begin(), info.bundleName);
354 
355     auto newEnd = std::remove_if(props.begin(), props.end(), [&enableVec](const auto &prop) {
356         return std::find(enableVec.begin(), enableVec.end(), prop.name) != enableVec.end();
357     });
358     props.erase(newEnd, props.end());
359     return ErrorCode::NO_ERROR;
360 }
361 
GetSwitchInfoBySwitchCount(SwitchInfo & switchInfo,int32_t userId,bool enableOn,uint32_t cacheCount)362 int32_t ImeInfoInquirer::GetSwitchInfoBySwitchCount(
363     SwitchInfo &switchInfo, int32_t userId, bool enableOn, uint32_t cacheCount)
364 {
365     std::vector<Property> props;
366     auto ret = ListEnabledInputMethod(userId, props, enableOn);
367     if (ret != ErrorCode::NO_ERROR) {
368         IMSA_HILOGE("userId: %{public}d ListEnabledInputMethod failed!", userId);
369         return ret;
370     }
371     auto currentImeBundle = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId)->bundleName;
372     auto iter = std::find_if(props.begin(), props.end(),
373         [&currentImeBundle](const Property &property) { return property.name == currentImeBundle; });
374     if (iter == props.end()) {
375         IMSA_HILOGE("can not found current ime in enable list");
376         auto info = GetDefaultImeInfo(userId);
377         if (info != nullptr) {
378             switchInfo.bundleName = info->prop.name;
379             return ErrorCode::NO_ERROR;
380         }
381         IMSA_HILOGE("bundle manager error!");
382         return ErrorCode::ERROR_PACKAGE_MANAGER;
383     }
384     uint32_t nextIndex = (cacheCount + static_cast<uint32_t>(std::distance(props.begin(), iter))) % props.size();
385     switchInfo.bundleName = props[nextIndex].name;
386     IMSA_HILOGD("next ime: %{public}s", switchInfo.bundleName.c_str());
387     return ErrorCode::NO_ERROR;
388 }
389 
ListInputMethodSubtype(int32_t userId,const std::string & bundleName,std::vector<SubProperty> & subProps)390 int32_t ImeInfoInquirer::ListInputMethodSubtype(
391     int32_t userId, const std::string &bundleName, std::vector<SubProperty> &subProps)
392 {
393     IMSA_HILOGD("userId: %{public}d, bundleName: %{public}s.", userId, bundleName.c_str());
394     auto infos = FullImeInfoManager::GetInstance().Get(userId);
395     auto it = std::find_if(
396         infos.begin(), infos.end(), [&bundleName](const FullImeInfo &info) { return info.prop.name == bundleName; });
397     if (it != infos.end()) {
398         subProps = (*it).subProps;
399         return ErrorCode::NO_ERROR;
400     }
401 
402     IMSA_HILOGD("%{public}d get %{public}s all subProp form bms.", userId, bundleName.c_str());
403     std::vector<ExtensionAbilityInfo> extInfos;
404     auto ret = GetExtInfosByBundleName(userId, bundleName, extInfos);
405     if (ret != ErrorCode::NO_ERROR) {
406         IMSA_HILOGE("userId: %{public}d getExtInfosByBundleName %{public}s failed!", userId, bundleName.c_str());
407         return ret;
408     }
409     return IsNewExtInfos(extInfos) ? ListInputMethodSubtype(userId, extInfos[0], subProps)
410                                    : ListInputMethodSubtype(userId, extInfos, subProps);
411 }
412 
ListCurrentInputMethodSubtype(int32_t userId,std::vector<SubProperty> & subProps)413 int32_t ImeInfoInquirer::ListCurrentInputMethodSubtype(int32_t userId, std::vector<SubProperty> &subProps)
414 {
415     auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
416     IMSA_HILOGD("currentIme: %{public}s.", currentImeCfg->imeId.c_str());
417     return ListInputMethodSubtype(userId, currentImeCfg->bundleName, subProps);
418 }
419 
IsNewExtInfos(const std::vector<ExtensionAbilityInfo> & extInfos)420 bool ImeInfoInquirer::IsNewExtInfos(const std::vector<ExtensionAbilityInfo> &extInfos)
421 {
422     if (extInfos.empty()) {
423         IMSA_HILOGE("extInfos is empty!");
424         return false;
425     }
426     auto iter = std::find_if(extInfos[0].metadata.begin(), extInfos[0].metadata.end(),
427         [](const Metadata &metadata) { return metadata.name == SUBTYPE_PROFILE_METADATA_NAME; });
428     return iter != extInfos[0].metadata.end();
429 }
430 
GetSubProperty(int32_t userId,const std::string & subName,const std::vector<OHOS::AppExecFwk::ExtensionAbilityInfo> & extInfos,SubProperty & subProp)431 int32_t ImeInfoInquirer::GetSubProperty(int32_t userId, const std::string &subName,
432     const std::vector<OHOS::AppExecFwk::ExtensionAbilityInfo> &extInfos, SubProperty &subProp)
433 {
434     IMSA_HILOGD("oldIme, userId: %{public}d.", userId);
435     if (extInfos.empty()) {
436         IMSA_HILOGE("extInfos is empty");
437         return ErrorCode::ERROR_PACKAGE_MANAGER;
438     }
439     auto extInfo = std::find_if(extInfos.begin(), extInfos.end(),
440         [&subName](const ExtensionAbilityInfo &info) { return info.name == subName; });
441     if (extInfo == extInfos.end()) {
442         IMSA_HILOGE("subtype %{public}s not found", subName.c_str());
443         extInfo = extInfos.begin();
444     }
445     subProp.labelId = extInfo->labelId;
446     subProp.label = GetStringById(extInfo->bundleName, extInfo->moduleName, extInfo->labelId, userId);
447     subProp.id = extInfo->name;
448     subProp.name = extInfo->bundleName;
449     subProp.iconId = extInfo->iconId;
450     std::vector<Metadata> extends = extInfo->metadata;
451     auto property = GetExtends(extends);
452     subProp.language = property.language;
453     subProp.mode = property.mode;
454     subProp.locale = property.locale;
455     subProp.icon = property.icon;
456     return ErrorCode::NO_ERROR;
457 }
458 
ListInputMethodSubtype(const int32_t userId,const std::vector<ExtensionAbilityInfo> & extInfos,std::vector<SubProperty> & subProps)459 int32_t ImeInfoInquirer::ListInputMethodSubtype(const int32_t userId,
460     const std::vector<ExtensionAbilityInfo> &extInfos, std::vector<SubProperty> &subProps)
461 {
462     IMSA_HILOGD("oldIme, userId: %{public}d.", userId);
463     for (const auto &extInfo : extInfos) {
464         SubProperty subProperty;
465         subProperty.labelId = extInfo.labelId;
466         subProperty.label = GetStringById(extInfo.bundleName, extInfo.moduleName, extInfo.labelId, userId);
467         subProperty.id = extInfo.name;
468         subProperty.name = extInfo.bundleName;
469         subProperty.iconId = extInfo.iconId;
470         std::vector<Metadata> extends = extInfo.metadata;
471         auto property = GetExtends(extends);
472         subProperty.language = property.language;
473         subProperty.mode = property.mode;
474         subProperty.locale = property.locale;
475         subProperty.icon = property.icon;
476         subProps.emplace_back(subProperty);
477     }
478     return ErrorCode::NO_ERROR;
479 }
480 
GetSubProperty(int32_t userId,const std::string & subName,const OHOS::AppExecFwk::ExtensionAbilityInfo & extInfo,SubProperty & subProp)481 int32_t ImeInfoInquirer::GetSubProperty(int32_t userId, const std::string &subName,
482     const OHOS::AppExecFwk::ExtensionAbilityInfo &extInfo, SubProperty &subProp)
483 {
484     IMSA_HILOGD("newIme, userId: %{public}d.", userId);
485     std::vector<Subtype> subtypes;
486     auto ret = ParseSubtype(extInfo, subtypes);
487     if (ret != ErrorCode::NO_ERROR) {
488         IMSA_HILOGE("failed to parse subtype!");
489         return ret;
490     }
491     if (subtypes.empty()) {
492         IMSA_HILOGE("subtypes is empty");
493         return ErrorCode::ERROR_PACKAGE_MANAGER;
494     }
495     auto subtype = std::find_if(
496         subtypes.begin(), subtypes.end(), [&subName](const Subtype &subtype) { return subtype.id == subName; });
497     if (subtype == subtypes.end()) {
498         IMSA_HILOGE("subtype %{public}s not found", subName.c_str());
499         subtype = subtypes.begin();
500     }
501     subProp.label = subtype->label;
502     subProp.name = extInfo.bundleName;
503     subProp.id = subtype->id;
504     subProp.mode = subtype->mode;
505     subProp.locale = subtype->locale;
506     subProp.icon = subtype->icon;
507     auto pos = subProp.label.find(':');
508     if (pos != std::string::npos && pos + 1 < subProp.label.size()) {
509         int32_t labelId = atoi(subProp.label.substr(pos + 1).c_str());
510         if (labelId > 0) {
511             subProp.labelId = static_cast<uint32_t>(labelId);
512             subProp.label = GetStringById(extInfo.bundleName, extInfo.moduleName, subProp.labelId, userId);
513         }
514     }
515     pos = subProp.icon.find(':');
516     if (pos != std::string::npos && pos + 1 < subProp.icon.size()) {
517         int32_t iconId = atoi(subProp.icon.substr(pos + 1).c_str());
518         if (iconId > 0) {
519             subProp.iconId = static_cast<uint32_t>(iconId);
520         }
521     }
522     CovertToLanguage(subProp.locale, subProp.language);
523     return ErrorCode::NO_ERROR;
524 }
525 
ListInputMethodSubtype(const int32_t userId,const ExtensionAbilityInfo & extInfo,std::vector<SubProperty> & subProps)526 int32_t ImeInfoInquirer::ListInputMethodSubtype(const int32_t userId, const ExtensionAbilityInfo &extInfo,
527     std::vector<SubProperty> &subProps)
528 {
529     IMSA_HILOGD("newIme, userId: %{public}d.", userId);
530     std::vector<Subtype> subtypes;
531     auto ret = ParseSubtype(extInfo, subtypes);
532     if (ret != ErrorCode::NO_ERROR) {
533         IMSA_HILOGE("failed to parse subtype!");
534         return ret;
535     }
536 
537     std::string resPath = extInfo.hapPath.empty() ? extInfo.resourcePath : extInfo.hapPath;
538     auto resMgr = GetResMgr(resPath);
539     IMSA_HILOGD("subtypes size: %{public}zu.", subtypes.size());
540     for (const auto &subtype : subtypes) {
541         // subtype which provides a particular input type should not appear in the subtype list
542         if (InputTypeManager::GetInstance().IsInputType({ extInfo.bundleName, subtype.id })) {
543             continue;
544         }
545         SubProperty subProp{ .label = subtype.label,
546             .name = extInfo.bundleName,
547             .id = subtype.id,
548             .mode = subtype.mode,
549             .locale = subtype.locale,
550             .icon = subtype.icon};
551         auto pos = subProp.label.find(':');
552         if (pos != std::string::npos && pos + 1 < subProp.label.size()) {
553             int32_t labelId = atoi(subProp.label.substr(pos + 1).c_str());
554             if (labelId > 0) {
555                 subProp.labelId = static_cast<uint32_t>(labelId);
556             }
557         }
558         if (resMgr != nullptr) {
559             auto errValue = resMgr->GetStringById(subProp.labelId, subProp.label);
560             if (errValue != RState::SUCCESS) {
561                 IMSA_HILOGE("GetStringById failed, bundleName:%{public}s, id:%{public}d.", extInfo.bundleName.c_str(),
562                     subProp.labelId);
563             }
564         }
565         pos = subProp.icon.find(':');
566         if (pos != std::string::npos && pos + 1 < subProp.icon.size()) {
567             int32_t iconId = atoi(subProp.icon.substr(pos + 1).c_str());
568             if (iconId > 0) {
569                 subProp.iconId = static_cast<uint32_t>(iconId);
570             }
571         }
572         CovertToLanguage(subProp.locale, subProp.language);
573         subProps.emplace_back(subProp);
574     }
575     return ErrorCode::NO_ERROR;
576 }
577 
ParseSubtype(const OHOS::AppExecFwk::ExtensionAbilityInfo & extInfo,std::vector<Subtype> & subtypes)578 int32_t ImeInfoInquirer::ParseSubtype(const OHOS::AppExecFwk::ExtensionAbilityInfo &extInfo,
579     std::vector<Subtype> &subtypes)
580 {
581     auto iter = std::find_if(extInfo.metadata.begin(), extInfo.metadata.end(),
582         [](const Metadata &metadata) { return metadata.name == SUBTYPE_PROFILE_METADATA_NAME; });
583     if (iter == extInfo.metadata.end()) {
584         IMSA_HILOGE("find metadata name: SUBTYPE_PROFILE_METADATA_NAME failed");
585         return ErrorCode::ERROR_BAD_PARAMETERS;
586     }
587     OHOS::AppExecFwk::BundleMgrClientImpl clientImpl;
588     std::vector<std::string> profiles;
589     if (!clientImpl.GetResConfigFile(extInfo, iter->name, profiles)) {
590         IMSA_HILOGE("failed to GetProfileFromExtension ");
591         return ErrorCode::ERROR_PACKAGE_MANAGER;
592     }
593     SubtypeCfg subtypeCfg;
594     if (!ParseSubtypeProfile(profiles, subtypeCfg)) {
595         IMSA_HILOGE("failed to ParseSubTypeCfg");
596         return ErrorCode::ERROR_BAD_PARAMETERS;
597     }
598     subtypes = subtypeCfg.subtypes;
599     IMSA_HILOGD("success.");
600     return ErrorCode::NO_ERROR;
601 }
602 
CovertToLanguage(const std::string & locale,std::string & language)603 void ImeInfoInquirer::CovertToLanguage(const std::string &locale, std::string &language)
604 {
605     language = locale;
606     auto pos = locale.find('-');
607     if (pos != std::string::npos) {
608         language = locale.substr(0, pos);
609     }
610     // compatible with the locale configuration of original ime
611     pos = locale.find('_');
612     if (pos != std::string::npos) {
613         language = locale.substr(0, pos);
614     }
615     if (language == "en") {
616         language = "english";
617     }
618     if (language == "zh") {
619         language = "chinese";
620     }
621 }
622 
GetStringById(const std::string & bundleName,const std::string & moduleName,uint32_t labelId,int32_t userId)623 std::string ImeInfoInquirer::GetStringById(const std::string &bundleName, const std::string &moduleName,
624     uint32_t labelId, int32_t userId)
625 {
626     auto bundleMgr = GetBundleMgr();
627     return bundleMgr == nullptr ? "" : bundleMgr->GetStringById(bundleName, moduleName, labelId, userId);
628 }
629 
GetExtends(const std::vector<Metadata> & metaData)630 SubProperty ImeInfoInquirer::GetExtends(const std::vector<Metadata> &metaData)
631 {
632     SubProperty property;
633     for (const auto &data : metaData) {
634         if (data.name == "language") {
635             property.language = data.value;
636             continue;
637         }
638         if (data.name == "mode") {
639             property.mode = data.value;
640             continue;
641         }
642         if (data.name == "locale") {
643             property.locale = data.value;
644             continue;
645         }
646         if (data.name == "icon") {
647             property.icon = data.value;
648         }
649     }
650     return property;
651 }
652 
GetImeProperty(int32_t userId,const std::string & bundleName,const std::string & extName)653 std::shared_ptr<Property> ImeInfoInquirer::GetImeProperty(
654     int32_t userId, const std::string &bundleName, const std::string &extName)
655 {
656     IMSA_HILOGD("start, bundleName: %{public}s", bundleName.c_str());
657     std::vector<AppExecFwk::ExtensionAbilityInfo> extInfos;
658     auto ret = ImeInfoInquirer::GetInstance().GetExtInfosByBundleName(userId, bundleName, extInfos);
659     if (ret != ErrorCode::NO_ERROR || extInfos.empty()) {
660         IMSA_HILOGE("userId: %{public}d getExtInfosByBundleName %{public}s failed!", userId, bundleName.c_str());
661         return nullptr;
662     }
663     Property prop = { .name = extInfos[0].bundleName,
664         .id = extName.empty() ? extInfos[0].name : extName,
665         .label = GetTargetString(extInfos[0], ImeTargetString::LABEL, userId),
666         .labelId = extInfos[0].applicationInfo.labelId,
667         .iconId = extInfos[0].applicationInfo.iconId };
668     return std::make_shared<Property>(prop);
669 }
670 
GetCurrentInputMethod(int32_t userId)671 std::shared_ptr<Property> ImeInfoInquirer::GetCurrentInputMethod(int32_t userId)
672 {
673     auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
674     IMSA_HILOGD("currentIme: %{public}s.", currentImeCfg->imeId.c_str());
675     auto infos = FullImeInfoManager::GetInstance().Get(userId);
676     auto it = std::find_if(infos.begin(), infos.end(),
677         [&currentImeCfg](const FullImeInfo &info) { return info.prop.name == currentImeCfg->bundleName; });
678     if (it != infos.end()) {
679         auto prop = std::make_shared<Property>((*it).prop);
680         prop->id = currentImeCfg->extName;
681         return prop;
682     }
683 
684     IMSA_HILOGD("%{public}d get %{public}s prop form bms.", userId, currentImeCfg->bundleName.c_str());
685     return GetImeProperty(userId, currentImeCfg->bundleName, currentImeCfg->extName);
686 }
687 
GetCurrentSubtype(int32_t userId)688 std::shared_ptr<SubProperty> ImeInfoInquirer::GetCurrentSubtype(int32_t userId)
689 {
690     auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
691     IMSA_HILOGD("currentIme: %{public}s.", currentIme->imeId.c_str());
692     auto infos = FullImeInfoManager::GetInstance().Get(userId);
693     auto it = std::find_if(infos.begin(), infos.end(),
694         [&currentIme](const FullImeInfo &info) { return info.prop.name == currentIme->bundleName; });
695     if (it != infos.end() && !it->subProps.empty()) {
696         auto iter = std::find_if(it->subProps.begin(), it->subProps.end(),
697             [&currentIme](const SubProperty &subProp) { return subProp.id == currentIme->subName; });
698         if (iter != it->subProps.end()) {
699             return std::make_shared<SubProperty>(*iter);
700         }
701         IMSA_HILOGW("subtype %{public}s not found.", currentIme->subName.c_str());
702         ImeCfgManager::GetInstance().ModifyImeCfg({ userId, currentIme->imeId, it->subProps[0].id, false });
703         return std::make_shared<SubProperty>(it->subProps[0]);
704     }
705 
706     IMSA_HILOGD("%{public}d get [%{public}s, %{public}s] form bms.", userId, currentIme->bundleName.c_str(),
707         currentIme->subName.c_str());
708     std::vector<ExtensionAbilityInfo> extInfos;
709     auto ret = GetExtInfosByBundleName(userId, currentIme->bundleName, extInfos);
710     if (ret != ErrorCode::NO_ERROR) {
711         IMSA_HILOGE("failed to GetExtInfosByBundleName: %{public}s, ret: %{public}d", currentIme->bundleName.c_str(),
712             ret);
713         return nullptr;
714     }
715     SubProperty subProp;
716     ret = IsNewExtInfos(extInfos) ? GetSubProperty(userId, currentIme->subName, extInfos[0], subProp)
717                                   : GetSubProperty(userId, currentIme->subName, extInfos, subProp);
718     if (ret != ErrorCode::NO_ERROR) {
719         IMSA_HILOGE("get %{public}s property failed, ret: %{public}d!", currentIme->subName.c_str(), ret);
720         return nullptr;
721     }
722     return std::make_shared<SubProperty>(subProp);
723 }
724 
IsImeInstalled(const int32_t userId,const std::string & bundleName,const std::string & extName)725 bool ImeInfoInquirer::IsImeInstalled(const int32_t userId, const std::string &bundleName, const std::string &extName)
726 {
727     IMSA_HILOGD("userId: %{public}d, bundleName: %{public}s, extName: %{public}s.", userId, bundleName.c_str(),
728         extName.c_str());
729     std::vector<OHOS::AppExecFwk::ExtensionAbilityInfo> extInfos;
730     GetExtInfosByBundleName(userId, bundleName, extInfos);
731     auto iter = std::find_if(extInfos.begin(), extInfos.end(),
732         [&bundleName, &extName](const OHOS::AppExecFwk::ExtensionAbilityInfo &extInfo) {
733             return extInfo.bundleName == bundleName && extName == extInfo.name;
734         });
735     if (iter == extInfos.end()) {
736         IMSA_HILOGE("false");
737         return false;
738     }
739     IMSA_HILOGI("true");
740     return true;
741 }
742 
GetImeToStart(int32_t userId)743 std::shared_ptr<ImeNativeCfg> ImeInfoInquirer::GetImeToStart(int32_t userId)
744 {
745     auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
746     IMSA_HILOGD("userId: %{public}d, currentIme: %{public}s.", userId, currentImeCfg->imeId.c_str());
747     if (currentImeCfg->imeId.empty() || !IsImeInstalled(userId, currentImeCfg->bundleName, currentImeCfg->extName)) {
748         auto newIme = GetDefaultIme();
749         auto info = GetDefaultImeInfo(userId);
750         if (info == nullptr) {
751             IMSA_HILOGW("failed to GetDefaultImeInfo");
752             newIme.subName = "";
753         } else {
754             newIme.subName = info->subProp.id;
755         }
756         currentImeCfg->imeId.empty()
757             ? ImeCfgManager::GetInstance().AddImeCfg({ userId, newIme.imeId, newIme.subName, false })
758             : ImeCfgManager::GetInstance().ModifyImeCfg({ userId, newIme.imeId, newIme.subName, false});
759         return std::make_shared<ImeNativeCfg>(newIme);
760     }
761     return currentImeCfg;
762 }
763 
GetInputMethodConfig(const int32_t userId,AppExecFwk::ElementName & inputMethodConfig)764 int32_t ImeInfoInquirer::GetInputMethodConfig(const int32_t userId, AppExecFwk::ElementName &inputMethodConfig)
765 {
766     IMSA_HILOGD("userId: %{public}d.", userId);
767     if (systemConfig_.systemInputMethodConfigAbility.empty()) {
768         IMSA_HILOGW("inputMethodConfig systemInputMethodConfigAbility is nullptr");
769         return ErrorCode::NO_ERROR;
770     }
771     std::string bundleName = systemConfig_.systemInputMethodConfigAbility;
772     std::string moduleName;
773     std::string abilityName;
774     auto pos = bundleName.find('/');
775     if (pos != std::string::npos) {
776         abilityName = (pos + 1 < bundleName.size()) ? bundleName.substr(pos + 1) : "";
777         bundleName = bundleName.substr(0, pos);
778     }
779     pos = abilityName.find('/');
780     if (pos != std::string::npos) {
781         moduleName = abilityName.substr(0, pos);
782         abilityName = (pos + 1 < abilityName.size()) ? abilityName.substr(pos + 1) : "";
783     }
784     inputMethodConfig.SetBundleName(std::move(bundleName));
785     inputMethodConfig.SetModuleName(std::move(moduleName));
786     inputMethodConfig.SetAbilityName(std::move(abilityName));
787     return ErrorCode::NO_ERROR;
788 }
789 
GetDefaultInputMethod(const int32_t userId,std::shared_ptr<Property> & prop,bool isBrief)790 int32_t ImeInfoInquirer::GetDefaultInputMethod(const int32_t userId, std::shared_ptr<Property> &prop, bool isBrief)
791 {
792     IMSA_HILOGD("userId: %{public}d.", userId);
793     auto defaultIme = GetDefaultImeCfgProp();
794     if (defaultIme == nullptr) {
795         IMSA_HILOGE("abnormal default ime cfg.");
796         return ErrorCode::ERROR_NULL_POINTER;
797     }
798     auto infos = FullImeInfoManager::GetInstance().Get(userId);
799     auto it = std::find_if(infos.begin(), infos.end(),
800         [&defaultIme](const FullImeInfo &info) { return info.prop.name == defaultIme->name; });
801     if (it != infos.end()) {
802         prop = std::make_shared<Property>((*it).prop);
803         prop->id = defaultIme->id;
804         return ErrorCode::NO_ERROR;
805     }
806 
807     IMSA_HILOGD("%{public}d get %{public}s form bms.", userId, defaultIme->name.c_str());
808     if (isBrief) {
809         IMSA_HILOGD("get brief info.");
810         if (prop == nullptr) {
811             prop = std::make_shared<Property>();
812         }
813         prop->name = defaultIme->name;
814         prop->id = defaultIme->id;
815         return ErrorCode::NO_ERROR;
816     }
817     prop = GetImeProperty(userId, defaultIme->name, defaultIme->id);
818     return ErrorCode::NO_ERROR;
819 }
820 
GetDefaultImeInfo(int32_t userId)821 std::shared_ptr<ImeInfo> ImeInfoInquirer::GetDefaultImeInfo(int32_t userId)
822 {
823     auto defaultIme = GetDefaultImeCfgProp();
824     if (defaultIme == nullptr) {
825         IMSA_HILOGE("defaultIme is nullptr!");
826         return nullptr;
827     }
828     auto info = GetImeInfo(userId, defaultIme->name, "");
829     if (info == nullptr) {
830         IMSA_HILOGE("userId: %{public}d, bundleName: %{public}s getImeInfoFromBundleMgr failed!", userId,
831             defaultIme->name.c_str());
832         return nullptr;
833     }
834     if (!info->isNewIme) {
835         info->prop.id = defaultIme->id;
836         auto it = std::find_if(info->subProps.begin(), info->subProps.end(),
837             [defaultIme](const SubProperty &subProp) { return subProp.id == defaultIme->id; });
838         if (it != info->subProps.end()) {
839             info->subProp = *it;
840         }
841     }
842     return info;
843 }
844 
GetDefaultIme()845 ImeNativeCfg ImeInfoInquirer::GetDefaultIme()
846 {
847     ImeNativeCfg imeCfg;
848     if (!systemConfig_.defaultInputMethod.empty()) {
849         IMSA_HILOGI("defaultInputMethod: %{public}s.", systemConfig_.defaultInputMethod.c_str());
850         imeCfg.imeId = systemConfig_.defaultInputMethod;
851     } else {
852         char value[CONFIG_LEN] = { 0 };
853         auto code = GetParameter(DEFAULT_IME_KEY, "", value, CONFIG_LEN);
854         imeCfg.imeId = code > 0 ? value : "";
855     }
856     auto pos = imeCfg.imeId.find('/');
857     if (pos == std::string::npos || pos + 1 >= imeCfg.imeId.size()) {
858         IMSA_HILOGE("defaultIme: %{public}s is abnormal!", imeCfg.imeId.c_str());
859         return {};
860     }
861     imeCfg.bundleName = imeCfg.imeId.substr(0, pos);
862     imeCfg.extName = imeCfg.imeId.substr(pos + 1);
863     return imeCfg;
864 }
865 
GetBundleMgr()866 sptr<OHOS::AppExecFwk::IBundleMgr> ImeInfoInquirer::GetBundleMgr()
867 {
868     sptr<ISystemAbilityManager> systemAbilityManager =
869         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
870     if (systemAbilityManager == nullptr) {
871         IMSA_HILOGE("systemAbilityManager is nullptr!");
872         return nullptr;
873     }
874     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
875     if (remoteObject == nullptr) {
876         IMSA_HILOGE("remoteObject is nullptr!");
877         return nullptr;
878     }
879     return iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
880 }
881 
FindTargetSubtypeByCondition(const std::vector<SubProperty> & subProps,const Condition & condition)882 std::shared_ptr<SubProperty> ImeInfoInquirer::FindTargetSubtypeByCondition(
883     const std::vector<SubProperty> &subProps, const Condition &condition)
884 {
885     auto it = subProps.end();
886     switch (condition) {
887         case Condition::UPPER: {
888             it = std::find_if(
889                 subProps.begin(), subProps.end(), [](const SubProperty &subProp) { return subProp.mode == "upper"; });
890             break;
891         }
892         case Condition::LOWER: {
893             it = std::find_if(
894                 subProps.begin(), subProps.end(), [](const SubProperty &subProp) { return subProp.mode == "lower"; });
895             break;
896         }
897         case Condition::ENGLISH: {
898             it = std::find_if(subProps.begin(), subProps.end(),
899                 [](const SubProperty &subProp) { return subProp.language == "english" && subProp.mode == "lower"; });
900             break;
901         }
902         case Condition::CHINESE: {
903             it = std::find_if(subProps.begin(), subProps.end(),
904                 [](const SubProperty &subProp) { return subProp.language == "chinese"; });
905             break;
906         }
907         default: {
908             break;
909         }
910     }
911     if (it == subProps.end()) {
912         return nullptr;
913     }
914     return std::make_shared<SubProperty>(*it);
915 }
916 
ParseSubtypeProfile(const std::vector<std::string> & profiles,SubtypeCfg & subtypeCfg)917 bool ImeInfoInquirer::ParseSubtypeProfile(const std::vector<std::string> &profiles, SubtypeCfg &subtypeCfg)
918 {
919     if (profiles.empty() || profiles.size() != SUBTYPE_PROFILE_NUM) {
920         IMSA_HILOGE("profiles size: %{public}zu!", profiles.size());
921         return false;
922     }
923     return subtypeCfg.Unmarshall(profiles[0]);
924 }
925 
GetDefaultImeCfgProp()926 std::shared_ptr<Property> ImeInfoInquirer::GetDefaultImeCfgProp()
927 {
928     auto ime = GetDefaultIme();
929     if (ime.bundleName.empty() || ime.extName.empty()) {
930         IMSA_HILOGE("defaultIme is abnormal!");
931         return nullptr;
932     }
933     auto defaultIme = std::make_shared<Property>();
934     defaultIme->name = ime.bundleName;
935     defaultIme->id = ime.extName;
936     return defaultIme;
937 }
938 
GetDefaultImeCfg()939 std::shared_ptr<ImeNativeCfg> ImeInfoInquirer::GetDefaultImeCfg()
940 {
941     auto ime = GetDefaultIme();
942     if (ime.bundleName.empty() || ime.extName.empty()) {
943         IMSA_HILOGE("defaultIme is abnormal!");
944         return nullptr;
945     }
946     return std::make_shared<ImeNativeCfg>(ime);
947 }
948 
GetResMgr(const std::string & resourcePath)949 std::shared_ptr<ResourceManager> ImeInfoInquirer::GetResMgr(const std::string &resourcePath)
950 {
951     if (resourcePath.empty()) {
952         IMSA_HILOGE("resourcePath is empty.");
953         return nullptr;
954     }
955     std::shared_ptr<ResourceManager> resMgr(CreateResourceManager());
956     if (resMgr == nullptr) {
957         IMSA_HILOGE("resMgr is nullptr.");
958         return nullptr;
959     }
960     resMgr->AddResource(resourcePath.c_str());
961     std::unique_ptr<ResConfig> resConfig(CreateResConfig());
962     if (resConfig == nullptr) {
963         IMSA_HILOGE("resConfig is nullptr.");
964         return nullptr;
965     }
966     std::map<std::string, std::string> configs;
967     OHOS::Global::I18n::LocaleInfo locale(Global::I18n::LocaleConfig::GetSystemLocale(), configs);
968     resConfig->SetLocaleInfo(locale.GetLanguage().c_str(), locale.GetScript().c_str(), locale.GetRegion().c_str());
969     resMgr->UpdateResConfig(*resConfig);
970     return resMgr;
971 }
972 
QueryFullImeInfo(std::vector<std::pair<int32_t,std::vector<FullImeInfo>>> & fullImeInfos)973 int32_t ImeInfoInquirer::QueryFullImeInfo(std::vector<std::pair<int32_t, std::vector<FullImeInfo>>> &fullImeInfos)
974 {
975     auto userIds = OsAccountAdapter::QueryActiveOsAccountIds();
976     if (userIds.empty()) {
977         return ErrorCode::ERROR_OS_ACCOUNT;
978     }
979     for (auto &userId : userIds) {
980         std::vector<FullImeInfo> infos;
981         auto errNo = QueryFullImeInfo(userId, infos);
982         if (errNo != ErrorCode::NO_ERROR) {
983             continue;
984         }
985         fullImeInfos.emplace_back(userId, infos);
986     }
987     if (fullImeInfos.empty()) {
988         return ErrorCode::ERROR_PACKAGE_MANAGER;
989     }
990     return ErrorCode::NO_ERROR;
991 }
992 
QueryFullImeInfo(int32_t userId,std::vector<FullImeInfo> & imeInfo)993 int32_t ImeInfoInquirer::QueryFullImeInfo(int32_t userId, std::vector<FullImeInfo> &imeInfo)
994 {
995     std::vector<ExtensionAbilityInfo> extInfos;
996     auto ret = ImeInfoInquirer::GetInstance().QueryImeExtInfos(userId, extInfos);
997     if (!ret || extInfos.empty()) {
998         IMSA_HILOGE("%{public}d QueryImeExtInfos failed.", userId);
999         return ErrorCode::ERROR_PACKAGE_MANAGER;
1000     }
1001     std::map<std::string, std::vector<ExtensionAbilityInfo>> tempExtInfos;
1002     for (const auto &extInfo : extInfos) {
1003         if (IsTempInputMethod(extInfo)) {
1004             continue;
1005         }
1006         auto it = tempExtInfos.find(extInfo.bundleName);
1007         if (it != tempExtInfos.end()) {
1008             it->second.push_back(extInfo);
1009             continue;
1010         }
1011         tempExtInfos.insert({ extInfo.bundleName, { extInfo } });
1012     }
1013 
1014     for (const auto &extInfo : tempExtInfos) {
1015         FullImeInfo info;
1016         auto errNo = GetFullImeInfo(userId, extInfo.second, info);
1017         if (errNo != ErrorCode::NO_ERROR) {
1018             return errNo;
1019         }
1020         imeInfo.push_back(info);
1021     }
1022     return ErrorCode::NO_ERROR;
1023 }
1024 
GetFullImeInfo(int32_t userId,const std::string & bundleName,FullImeInfo & imeInfo)1025 int32_t ImeInfoInquirer::GetFullImeInfo(int32_t userId, const std::string &bundleName, FullImeInfo &imeInfo)
1026 {
1027     std::vector<ExtensionAbilityInfo> extInfos;
1028     auto ret = ImeInfoInquirer::GetInstance().QueryImeExtInfos(userId, extInfos);
1029     if (!ret || extInfos.empty()) {
1030         return ErrorCode::ERROR_PACKAGE_MANAGER;
1031     }
1032     std::vector<ExtensionAbilityInfo> tempExtInfos;
1033     for (const auto &extInfo : extInfos) {
1034         if (IsTempInputMethod(extInfo)) {
1035             continue;
1036         }
1037         if (extInfo.bundleName == bundleName) {
1038             tempExtInfos.push_back(extInfo);
1039         }
1040     }
1041     return GetFullImeInfo(userId, tempExtInfos, imeInfo);
1042 }
1043 
GetFullImeInfo(int32_t userId,const std::vector<OHOS::AppExecFwk::ExtensionAbilityInfo> & extInfos,FullImeInfo & imeInfo)1044 int32_t ImeInfoInquirer::GetFullImeInfo(
1045     int32_t userId, const std::vector<OHOS::AppExecFwk::ExtensionAbilityInfo> &extInfos, FullImeInfo &imeInfo)
1046 {
1047     if (extInfos.empty()) {
1048         return ErrorCode::ERROR_PACKAGE_MANAGER;
1049     }
1050     imeInfo.isNewIme = IsNewExtInfos(extInfos);
1051     auto ret = imeInfo.isNewIme ? ListInputMethodSubtype(userId, extInfos[0], imeInfo.subProps)
1052                         : ListInputMethodSubtype(userId, extInfos, imeInfo.subProps);
1053     if (ret != ErrorCode::NO_ERROR) {
1054         IMSA_HILOGE("[%{public}d,%{public}s] list Subtype failed.", userId, extInfos[0].bundleName.c_str());
1055         return ret;
1056     }
1057     imeInfo.tokenId = extInfos[0].applicationInfo.accessTokenId;
1058     imeInfo.prop.name = extInfos[0].bundleName;
1059     imeInfo.prop.id = extInfos[0].name;
1060     imeInfo.prop.label = GetTargetString(extInfos[0], ImeTargetString::LABEL, userId);
1061     imeInfo.prop.labelId = extInfos[0].applicationInfo.labelId;
1062     imeInfo.prop.iconId = extInfos[0].applicationInfo.iconId;
1063     BundleInfo bundleInfo;
1064     if (GetBundleInfoByBundleName(userId, imeInfo.prop.name, bundleInfo)) {
1065         imeInfo.appId = bundleInfo.signatureInfo.appIdentifier;
1066         imeInfo.versionCode = bundleInfo.versionCode;
1067     }
1068     return ErrorCode::NO_ERROR;
1069 }
1070 
IsInputMethod(int32_t userId,const std::string & bundleName)1071 bool ImeInfoInquirer::IsInputMethod(int32_t userId, const std::string &bundleName)
1072 {
1073     auto bmg = GetBundleMgr();
1074     if (bmg == nullptr) {
1075         return false;
1076     }
1077     BundleInfo bundleInfo;
1078     auto ret = bmg->GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, userId);
1079     if (!ret) {
1080         return false;
1081     }
1082     for (const auto &extInfo : bundleInfo.extensionInfos) {
1083         if (extInfo.type == ExtensionAbilityType::INPUTMETHOD) {
1084             return true;
1085         }
1086     }
1087     return false;
1088 }
1089 
IsTempInputMethod(const ExtensionAbilityInfo & extInfo)1090 bool ImeInfoInquirer::IsTempInputMethod(const ExtensionAbilityInfo &extInfo)
1091 {
1092     auto iter = std::find_if(extInfo.metadata.begin(), extInfo.metadata.end(),
1093         [](const Metadata &metadata) {
1094             return metadata.name == TEMPORARY_INPUT_METHOD_METADATA_NAME;
1095         });
1096     return iter != extInfo.metadata.end();
1097 }
1098 
GetRunningIme(int32_t userId)1099 std::vector<std::string> ImeInfoInquirer::GetRunningIme(int32_t userId)
1100 {
1101     std::vector<std::string> bundleNames;
1102     std::vector<RunningProcessInfo> infos;
1103     AppMgrClient client;
1104     auto ret = client.GetProcessRunningInfosByUserId(infos, userId);
1105     if (ret != ErrorCode::NO_ERROR) {
1106         IMSA_HILOGE("GetAllRunningProcesses failed, ret: %{public}d!", ret);
1107         return bundleNames;
1108     }
1109     for (const auto &info : infos) {
1110         if (info.extensionType_ == ExtensionAbilityType::INPUTMETHOD && !info.bundleNames.empty()) {
1111             bundleNames.push_back(info.bundleNames[0]);
1112         }
1113     }
1114     return bundleNames;
1115 }
1116 
IsDefaultImeSet(int32_t userId)1117 bool ImeInfoInquirer::IsDefaultImeSet(int32_t userId)
1118 {
1119     return ImeCfgManager::GetInstance().IsDefaultImeSet(userId);
1120 }
1121 
IsRunningIme(int32_t userId,const std::string & bundleName)1122 bool ImeInfoInquirer::IsRunningIme(int32_t userId, const std::string &bundleName)
1123 {
1124     auto bundleNames = GetRunningIme(userId);
1125     auto it = std::find_if(bundleNames.begin(), bundleNames.end(),
1126         [&bundleName](const std::string &bundleNameTemp) { return bundleName == bundleNameTemp; });
1127     return it != bundleNames.end();
1128 }
1129 
GetImeAppId(int32_t userId,const std::string & bundleName,std::string & appId)1130 bool ImeInfoInquirer::GetImeAppId(int32_t userId, const std::string &bundleName, std::string &appId)
1131 {
1132     FullImeInfo imeInfo;
1133     if (FullImeInfoManager::GetInstance().Get(bundleName, userId, imeInfo) && !imeInfo.appId.empty()) {
1134         appId = imeInfo.appId;
1135         return true;
1136     }
1137     BundleInfo bundleInfo;
1138     if (!GetBundleInfoByBundleName(userId, bundleName, bundleInfo)) {
1139         return false;
1140     }
1141     appId = bundleInfo.signatureInfo.appIdentifier;
1142     return !appId.empty();
1143 }
1144 
GetImeVersionCode(int32_t userId,const std::string & bundleName,uint32_t & versionCode)1145 bool ImeInfoInquirer::GetImeVersionCode(int32_t userId, const std::string &bundleName, uint32_t &versionCode)
1146 {
1147     FullImeInfo imeInfo;
1148     if (FullImeInfoManager::GetInstance().Get(bundleName, userId, imeInfo)) {
1149         versionCode = imeInfo.versionCode;
1150         return true;
1151     }
1152     BundleInfo bundleInfo;
1153     if (!GetBundleInfoByBundleName(userId, bundleName, bundleInfo)) {
1154         return false;
1155     }
1156     versionCode = bundleInfo.versionCode;
1157     return true;
1158 }
1159 
GetBundleInfoByBundleName(int32_t userId,const std::string & bundleName,AppExecFwk::BundleInfo & bundleInfo)1160 bool ImeInfoInquirer::GetBundleInfoByBundleName(
1161     int32_t userId, const std::string &bundleName, AppExecFwk::BundleInfo &bundleInfo)
1162 {
1163     auto bundleMgr = GetBundleMgr();
1164     if (bundleMgr == nullptr) {
1165         IMSA_HILOGE("failed to get bundleMgr!");
1166         return false;
1167     }
1168     auto ret = bundleMgr->GetBundleInfo(
1169         bundleName, static_cast<int32_t>(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_SIGNATURE_INFO), bundleInfo, userId);
1170     if (!ret) {
1171         IMSA_HILOGE("failed to get bundle info");
1172         return false;
1173     }
1174     return true;
1175 }
1176 
GetTargetString(const AppExecFwk::ExtensionAbilityInfo & extension,ImeTargetString target,int32_t userId)1177 std::string ImeInfoInquirer::GetTargetString(
1178     const AppExecFwk::ExtensionAbilityInfo &extension, ImeTargetString target, int32_t userId)
1179 {
1180     if (target == ImeTargetString::LABEL) {
1181         if (extension.labelId != DEFAULT_BMS_VALUE) {
1182             return GetStringById(extension.bundleName, extension.moduleName, extension.labelId, userId);
1183         }
1184         IMSA_HILOGD("Extension label is empty, get application label");
1185         return GetStringById(extension.bundleName, extension.applicationInfo.labelResource.moduleName,
1186             extension.applicationInfo.labelResource.id, userId);
1187     }
1188     if (target == ImeTargetString::DESCRIPTION) {
1189         if (extension.descriptionId != DEFAULT_BMS_VALUE) {
1190             return GetStringById(extension.bundleName, extension.moduleName, extension.descriptionId, userId);
1191         }
1192         IMSA_HILOGD("extension description is empty, get application description");
1193         return GetStringById(extension.bundleName, extension.applicationInfo.descriptionResource.moduleName,
1194             extension.applicationInfo.descriptionResource.id, userId);
1195     }
1196     IMSA_HILOGD("No match target string");
1197     return "";
1198 }
1199 } // namespace MiscServices
1200 } // namespace OHOS