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(const int32_t userId, const std::string &bundleName,
95     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(int32_t userId, InputMethodStatus status, std::vector<Property> &props,
255     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(SwitchInfo &switchInfo, int32_t userId, bool enableOn,
363     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(int32_t userId, const std::string &bundleName,
391     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     if (extInfo.metadata.empty()) {
582         IMSA_HILOGE("metadata is empty!");
583         return ErrorCode::ERROR_BAD_PARAMETERS;
584     }
585     auto iter = std::find_if(extInfo.metadata.begin(), extInfo.metadata.end(),
586         [](const Metadata &metadata) { return metadata.name == SUBTYPE_PROFILE_METADATA_NAME; });
587     if (iter == extInfo.metadata.end()) {
588         IMSA_HILOGE("find metadata name: SUBTYPE_PROFILE_METADATA_NAME failed!");
589         return ErrorCode::ERROR_BAD_PARAMETERS;
590     }
591     OHOS::AppExecFwk::BundleMgrClientImpl clientImpl;
592     std::vector<std::string> profiles;
593     if (!clientImpl.GetResConfigFile(extInfo, iter->name, profiles)) {
594         IMSA_HILOGE("failed to GetProfileFromExtension!");
595         return ErrorCode::ERROR_PACKAGE_MANAGER;
596     }
597     SubtypeCfg subtypeCfg;
598     if (!ParseSubtypeProfile(profiles, subtypeCfg)) {
599         IMSA_HILOGE("failed to ParseSubTypeCfg!");
600         return ErrorCode::ERROR_BAD_PARAMETERS;
601     }
602     subtypes = subtypeCfg.subtypes;
603     IMSA_HILOGD("success.");
604     return ErrorCode::NO_ERROR;
605 }
606 
CovertToLanguage(const std::string &locale, std::string &language)607 void ImeInfoInquirer::CovertToLanguage(const std::string &locale, std::string &language)
608 {
609     language = locale;
610     auto pos = locale.find('-');
611     if (pos != std::string::npos) {
612         language = locale.substr(0, pos);
613     }
614     // compatible with the locale configuration of original ime
615     pos = locale.find('_');
616     if (pos != std::string::npos) {
617         language = locale.substr(0, pos);
618     }
619     if (language == "en") {
620         language = "english";
621     }
622     if (language == "zh") {
623         language = "chinese";
624     }
625 }
626 
GetStringById(const std::string &bundleName, const std::string &moduleName, uint32_t labelId, int32_t userId)627 std::string ImeInfoInquirer::GetStringById(const std::string &bundleName, const std::string &moduleName,
628     uint32_t labelId, int32_t userId)
629 {
630     auto bundleMgr = GetBundleMgr();
631     return bundleMgr == nullptr ? "" : bundleMgr->GetStringById(bundleName, moduleName, labelId, userId);
632 }
633 
GetExtends(const std::vector<Metadata> &metaData)634 SubProperty ImeInfoInquirer::GetExtends(const std::vector<Metadata> &metaData)
635 {
636     SubProperty property;
637     for (const auto &data : metaData) {
638         if (data.name == "language") {
639             property.language = data.value;
640             continue;
641         }
642         if (data.name == "mode") {
643             property.mode = data.value;
644             continue;
645         }
646         if (data.name == "locale") {
647             property.locale = data.value;
648             continue;
649         }
650         if (data.name == "icon") {
651             property.icon = data.value;
652         }
653     }
654     return property;
655 }
656 
GetImeProperty( int32_t userId, const std::string &bundleName, const std::string &extName)657 std::shared_ptr<Property> ImeInfoInquirer::GetImeProperty(
658     int32_t userId, const std::string &bundleName, const std::string &extName)
659 {
660     IMSA_HILOGD("start, bundleName: %{public}s", bundleName.c_str());
661     std::vector<AppExecFwk::ExtensionAbilityInfo> extInfos;
662     auto ret = ImeInfoInquirer::GetInstance().GetExtInfosByBundleName(userId, bundleName, extInfos);
663     if (ret != ErrorCode::NO_ERROR || extInfos.empty()) {
664         IMSA_HILOGE("userId: %{public}d getExtInfosByBundleName %{public}s failed!", userId, bundleName.c_str());
665         return nullptr;
666     }
667     Property prop = { .name = extInfos[0].bundleName,
668         .id = extName.empty() ? extInfos[0].name : extName,
669         .label = GetTargetString(extInfos[0], ImeTargetString::LABEL, userId),
670         .labelId = extInfos[0].applicationInfo.labelId,
671         .iconId = extInfos[0].applicationInfo.iconId };
672     return std::make_shared<Property>(prop);
673 }
674 
GetCurrentInputMethod(int32_t userId)675 std::shared_ptr<Property> ImeInfoInquirer::GetCurrentInputMethod(int32_t userId)
676 {
677     auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
678     IMSA_HILOGD("currentIme: %{public}s.", currentImeCfg->imeId.c_str());
679     auto infos = FullImeInfoManager::GetInstance().Get(userId);
680     auto it = std::find_if(infos.begin(), infos.end(),
681         [&currentImeCfg](const FullImeInfo &info) { return info.prop.name == currentImeCfg->bundleName; });
682     if (it != infos.end()) {
683         auto prop = std::make_shared<Property>((*it).prop);
684         prop->id = currentImeCfg->extName;
685         return prop;
686     }
687 
688     IMSA_HILOGD("%{public}d get %{public}s prop form bms.", userId, currentImeCfg->bundleName.c_str());
689     return GetImeProperty(userId, currentImeCfg->bundleName, currentImeCfg->extName);
690 }
691 
GetCurrentSubtype(int32_t userId)692 std::shared_ptr<SubProperty> ImeInfoInquirer::GetCurrentSubtype(int32_t userId)
693 {
694     auto currentIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
695     IMSA_HILOGD("currentIme: %{public}s.", currentIme->imeId.c_str());
696     auto infos = FullImeInfoManager::GetInstance().Get(userId);
697     auto it = std::find_if(infos.begin(), infos.end(),
698         [&currentIme](const FullImeInfo &info) { return info.prop.name == currentIme->bundleName; });
699     if (it != infos.end() && !it->subProps.empty()) {
700         auto iter = std::find_if(it->subProps.begin(), it->subProps.end(),
701             [&currentIme](const SubProperty &subProp) { return subProp.id == currentIme->subName; });
702         if (iter != it->subProps.end()) {
703             return std::make_shared<SubProperty>(*iter);
704         }
705         IMSA_HILOGW("subtype %{public}s not found.", currentIme->subName.c_str());
706         ImeCfgManager::GetInstance().ModifyImeCfg({ userId, currentIme->imeId, it->subProps[0].id, false });
707         return std::make_shared<SubProperty>(it->subProps[0]);
708     }
709 
710     IMSA_HILOGD("%{public}d get [%{public}s, %{public}s] form bms.", userId, currentIme->bundleName.c_str(),
711         currentIme->subName.c_str());
712     std::vector<ExtensionAbilityInfo> extInfos;
713     auto ret = GetExtInfosByBundleName(userId, currentIme->bundleName, extInfos);
714     if (ret != ErrorCode::NO_ERROR) {
715         IMSA_HILOGE("failed to GetExtInfosByBundleName: %{public}s, ret: %{public}d", currentIme->bundleName.c_str(),
716             ret);
717         return nullptr;
718     }
719     SubProperty subProp;
720     ret = IsNewExtInfos(extInfos) ? GetSubProperty(userId, currentIme->subName, extInfos[0], subProp)
721                                   : GetSubProperty(userId, currentIme->subName, extInfos, subProp);
722     if (ret != ErrorCode::NO_ERROR) {
723         IMSA_HILOGE("get %{public}s property failed, ret: %{public}d!", currentIme->subName.c_str(), ret);
724         return nullptr;
725     }
726     return std::make_shared<SubProperty>(subProp);
727 }
728 
IsImeInstalled(const int32_t userId, const std::string &bundleName, const std::string &extName)729 bool ImeInfoInquirer::IsImeInstalled(const int32_t userId, const std::string &bundleName, const std::string &extName)
730 {
731     IMSA_HILOGD("userId: %{public}d, bundleName: %{public}s, extName: %{public}s.", userId, bundleName.c_str(),
732         extName.c_str());
733     std::vector<OHOS::AppExecFwk::ExtensionAbilityInfo> extInfos;
734     GetExtInfosByBundleName(userId, bundleName, extInfos);
735     auto iter = std::find_if(extInfos.begin(), extInfos.end(),
736         [&bundleName, &extName](const OHOS::AppExecFwk::ExtensionAbilityInfo &extInfo) {
737             return extInfo.bundleName == bundleName && extName == extInfo.name;
738         });
739     if (iter == extInfos.end()) {
740         IMSA_HILOGE("false");
741         return false;
742     }
743     IMSA_HILOGI("true");
744     return true;
745 }
746 
GetImeToStart(int32_t userId)747 std::shared_ptr<ImeNativeCfg> ImeInfoInquirer::GetImeToStart(int32_t userId)
748 {
749     auto currentImeCfg = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId);
750     IMSA_HILOGD("userId: %{public}d, currentIme: %{public}s.", userId, currentImeCfg->imeId.c_str());
751     if (currentImeCfg->imeId.empty() || !IsImeInstalled(userId, currentImeCfg->bundleName, currentImeCfg->extName)) {
752         auto newIme = GetDefaultIme();
753         auto info = GetDefaultImeInfo(userId);
754         if (info == nullptr) {
755             IMSA_HILOGW("failed to GetDefaultImeInfo");
756             newIme.subName = "";
757         } else {
758             newIme.subName = info->subProp.id;
759         }
760         currentImeCfg->imeId.empty()
761             ? ImeCfgManager::GetInstance().AddImeCfg({ userId, newIme.imeId, newIme.subName, false })
762             : ImeCfgManager::GetInstance().ModifyImeCfg({ userId, newIme.imeId, newIme.subName, false});
763         return std::make_shared<ImeNativeCfg>(newIme);
764     }
765     return currentImeCfg;
766 }
767 
GetInputMethodConfig(const int32_t userId, AppExecFwk::ElementName &inputMethodConfig)768 int32_t ImeInfoInquirer::GetInputMethodConfig(const int32_t userId, AppExecFwk::ElementName &inputMethodConfig)
769 {
770     IMSA_HILOGD("userId: %{public}d.", userId);
771     if (systemConfig_.systemInputMethodConfigAbility.empty()) {
772         IMSA_HILOGW("inputMethodConfig systemInputMethodConfigAbility is nullptr");
773         return ErrorCode::NO_ERROR;
774     }
775     std::string bundleName = systemConfig_.systemInputMethodConfigAbility;
776     std::string moduleName;
777     std::string abilityName;
778     auto pos = bundleName.find('/');
779     if (pos != std::string::npos) {
780         abilityName = (pos + 1 < bundleName.size()) ? bundleName.substr(pos + 1) : "";
781         bundleName = bundleName.substr(0, pos);
782     }
783     pos = abilityName.find('/');
784     if (pos != std::string::npos) {
785         moduleName = abilityName.substr(0, pos);
786         abilityName = (pos + 1 < abilityName.size()) ? abilityName.substr(pos + 1) : "";
787     }
788     inputMethodConfig.SetBundleName(std::move(bundleName));
789     inputMethodConfig.SetModuleName(std::move(moduleName));
790     inputMethodConfig.SetAbilityName(std::move(abilityName));
791     return ErrorCode::NO_ERROR;
792 }
793 
GetDefaultInputMethod(const int32_t userId, std::shared_ptr<Property> &prop, bool isBrief)794 int32_t ImeInfoInquirer::GetDefaultInputMethod(const int32_t userId, std::shared_ptr<Property> &prop, bool isBrief)
795 {
796     IMSA_HILOGD("userId: %{public}d.", userId);
797     auto defaultIme = GetDefaultImeCfgProp();
798     if (defaultIme == nullptr) {
799         IMSA_HILOGE("abnormal default ime cfg!");
800         return ErrorCode::ERROR_NULL_POINTER;
801     }
802     auto infos = FullImeInfoManager::GetInstance().Get(userId);
803     auto it = std::find_if(infos.begin(), infos.end(),
804         [&defaultIme](const FullImeInfo &info) { return info.prop.name == defaultIme->name; });
805     if (it != infos.end()) {
806         prop = std::make_shared<Property>((*it).prop);
807         prop->id = defaultIme->id;
808         return ErrorCode::NO_ERROR;
809     }
810 
811     IMSA_HILOGD("%{public}d get %{public}s form bms.", userId, defaultIme->name.c_str());
812     if (isBrief) {
813         IMSA_HILOGD("get brief info.");
814         if (prop == nullptr) {
815             prop = std::make_shared<Property>();
816         }
817         prop->name = defaultIme->name;
818         prop->id = defaultIme->id;
819         return ErrorCode::NO_ERROR;
820     }
821     prop = GetImeProperty(userId, defaultIme->name, defaultIme->id);
822     return ErrorCode::NO_ERROR;
823 }
824 
GetDefaultImeInfo(int32_t userId)825 std::shared_ptr<ImeInfo> ImeInfoInquirer::GetDefaultImeInfo(int32_t userId)
826 {
827     auto defaultIme = GetDefaultImeCfgProp();
828     if (defaultIme == nullptr) {
829         IMSA_HILOGE("defaultIme is nullptr!");
830         return nullptr;
831     }
832     auto info = GetImeInfo(userId, defaultIme->name, "");
833     if (info == nullptr) {
834         IMSA_HILOGE("userId: %{public}d, bundleName: %{public}s getImeInfoFromBundleMgr failed!", userId,
835             defaultIme->name.c_str());
836         return nullptr;
837     }
838     if (!info->isNewIme) {
839         info->prop.id = defaultIme->id;
840         auto it = std::find_if(info->subProps.begin(), info->subProps.end(),
841             [defaultIme](const SubProperty &subProp) { return subProp.id == defaultIme->id; });
842         if (it != info->subProps.end()) {
843             info->subProp = *it;
844         }
845     }
846     return info;
847 }
848 
GetDefaultIme()849 ImeNativeCfg ImeInfoInquirer::GetDefaultIme()
850 {
851     ImeNativeCfg imeCfg;
852     if (!systemConfig_.defaultInputMethod.empty()) {
853         IMSA_HILOGI("defaultInputMethod: %{public}s.", systemConfig_.defaultInputMethod.c_str());
854         imeCfg.imeId = systemConfig_.defaultInputMethod;
855     } else {
856         char value[CONFIG_LEN] = { 0 };
857         auto code = GetParameter(DEFAULT_IME_KEY, "", value, CONFIG_LEN);
858         imeCfg.imeId = code > 0 ? value : "";
859     }
860     auto pos = imeCfg.imeId.find('/');
861     if (pos == std::string::npos || pos + 1 >= imeCfg.imeId.size()) {
862         IMSA_HILOGE("defaultIme: %{public}s is abnormal!", imeCfg.imeId.c_str());
863         return {};
864     }
865     imeCfg.bundleName = imeCfg.imeId.substr(0, pos);
866     imeCfg.extName = imeCfg.imeId.substr(pos + 1);
867     return imeCfg;
868 }
869 
GetBundleMgr()870 sptr<OHOS::AppExecFwk::IBundleMgr> ImeInfoInquirer::GetBundleMgr()
871 {
872     sptr<ISystemAbilityManager> systemAbilityManager =
873         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
874     if (systemAbilityManager == nullptr) {
875         IMSA_HILOGE("systemAbilityManager is nullptr!");
876         return nullptr;
877     }
878     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
879     if (remoteObject == nullptr) {
880         IMSA_HILOGE("remoteObject is nullptr!");
881         return nullptr;
882     }
883     return iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
884 }
885 
FindTargetSubtypeByCondition(const std::vector<SubProperty> &subProps, const Condition &condition)886 std::shared_ptr<SubProperty> ImeInfoInquirer::FindTargetSubtypeByCondition(const std::vector<SubProperty> &subProps,
887     const Condition &condition)
888 {
889     auto it = subProps.end();
890     switch (condition) {
891         case Condition::UPPER: {
892             it = std::find_if(subProps.begin(), subProps.end(),
893                 [](const SubProperty &subProp) { return subProp.mode == "upper"; });
894             break;
895         }
896         case Condition::LOWER: {
897             it = std::find_if(subProps.begin(), subProps.end(),
898                 [](const SubProperty &subProp) { return subProp.mode == "lower"; });
899             break;
900         }
901         case Condition::ENGLISH: {
902             it = std::find_if(subProps.begin(), subProps.end(),
903                 [](const SubProperty &subProp) { return subProp.language == "english" && subProp.mode == "lower"; });
904             break;
905         }
906         case Condition::CHINESE: {
907             it = std::find_if(subProps.begin(), subProps.end(),
908                 [](const SubProperty &subProp) { return subProp.language == "chinese"; });
909             break;
910         }
911         default: {
912             break;
913         }
914     }
915     if (it == subProps.end()) {
916         return nullptr;
917     }
918     return std::make_shared<SubProperty>(*it);
919 }
920 
ParseSubtypeProfile(const std::vector<std::string> &profiles, SubtypeCfg &subtypeCfg)921 bool ImeInfoInquirer::ParseSubtypeProfile(const std::vector<std::string> &profiles, SubtypeCfg &subtypeCfg)
922 {
923     if (profiles.empty() || profiles.size() != SUBTYPE_PROFILE_NUM) {
924         IMSA_HILOGE("profiles size: %{public}zu!", profiles.size());
925         return false;
926     }
927     return subtypeCfg.Unmarshall(profiles[0]);
928 }
929 
GetDefaultImeCfgProp()930 std::shared_ptr<Property> ImeInfoInquirer::GetDefaultImeCfgProp()
931 {
932     auto ime = GetDefaultIme();
933     if (ime.bundleName.empty() || ime.extName.empty()) {
934         IMSA_HILOGE("defaultIme is abnormal!");
935         return nullptr;
936     }
937     auto defaultIme = std::make_shared<Property>();
938     defaultIme->name = ime.bundleName;
939     defaultIme->id = ime.extName;
940     return defaultIme;
941 }
942 
GetResMgr(const std::string &resourcePath)943 std::shared_ptr<ResourceManager> ImeInfoInquirer::GetResMgr(const std::string &resourcePath)
944 {
945     if (resourcePath.empty()) {
946         IMSA_HILOGE("resourcePath is empty!");
947         return nullptr;
948     }
949     std::shared_ptr<ResourceManager> resMgr(CreateResourceManager());
950     if (resMgr == nullptr) {
951         IMSA_HILOGE("resMgr is nullptr!");
952         return nullptr;
953     }
954     resMgr->AddResource(resourcePath.c_str());
955     std::unique_ptr<ResConfig> resConfig(CreateResConfig());
956     if (resConfig == nullptr) {
957         IMSA_HILOGE("resConfig is nullptr!");
958         return nullptr;
959     }
960     std::map<std::string, std::string> configs;
961     OHOS::Global::I18n::LocaleInfo locale(Global::I18n::LocaleConfig::GetSystemLocale(), configs);
962     resConfig->SetLocaleInfo(locale.GetLanguage().c_str(), locale.GetScript().c_str(), locale.GetRegion().c_str());
963     resMgr->UpdateResConfig(*resConfig);
964     return resMgr;
965 }
966 
QueryFullImeInfo(std::vector<std::pair<int32_t, std::vector<FullImeInfo>>> &fullImeInfos)967 int32_t ImeInfoInquirer::QueryFullImeInfo(std::vector<std::pair<int32_t, std::vector<FullImeInfo>>> &fullImeInfos)
968 {
969     auto userIds = OsAccountAdapter::QueryActiveOsAccountIds();
970     if (userIds.empty()) {
971         return ErrorCode::ERROR_OS_ACCOUNT;
972     }
973     for (auto &userId : userIds) {
974         std::vector<FullImeInfo> infos;
975         auto errNo = QueryFullImeInfo(userId, infos);
976         if (errNo != ErrorCode::NO_ERROR) {
977             continue;
978         }
979         fullImeInfos.emplace_back(userId, infos);
980     }
981     if (fullImeInfos.empty()) {
982         return ErrorCode::ERROR_PACKAGE_MANAGER;
983     }
984     return ErrorCode::NO_ERROR;
985 }
986 
QueryFullImeInfo(int32_t userId, std::vector<FullImeInfo> &imeInfo)987 int32_t ImeInfoInquirer::QueryFullImeInfo(int32_t userId, std::vector<FullImeInfo> &imeInfo)
988 {
989     std::vector<ExtensionAbilityInfo> extInfos;
990     auto ret = ImeInfoInquirer::GetInstance().QueryImeExtInfos(userId, extInfos);
991     if (!ret || extInfos.empty()) {
992         IMSA_HILOGE("%{public}d QueryImeExtInfos failed!", userId);
993         return ErrorCode::ERROR_PACKAGE_MANAGER;
994     }
995     std::map<std::string, std::vector<ExtensionAbilityInfo>> tempExtInfos;
996     for (const auto &extInfo : extInfos) {
997         if (IsTempInputMethod(extInfo)) {
998             continue;
999         }
1000         auto it = tempExtInfos.find(extInfo.bundleName);
1001         if (it != tempExtInfos.end()) {
1002             it->second.push_back(extInfo);
1003             continue;
1004         }
1005         tempExtInfos.insert({ extInfo.bundleName, { extInfo } });
1006     }
1007 
1008     for (const auto &extInfo : tempExtInfos) {
1009         FullImeInfo info;
1010         auto errNo = GetFullImeInfo(userId, extInfo.second, info);
1011         if (errNo != ErrorCode::NO_ERROR) {
1012             return errNo;
1013         }
1014         imeInfo.push_back(info);
1015     }
1016     return ErrorCode::NO_ERROR;
1017 }
1018 
GetFullImeInfo(int32_t userId, const std::string &bundleName, FullImeInfo &imeInfo)1019 int32_t ImeInfoInquirer::GetFullImeInfo(int32_t userId, const std::string &bundleName, FullImeInfo &imeInfo)
1020 {
1021     std::vector<ExtensionAbilityInfo> extInfos;
1022     auto ret = ImeInfoInquirer::GetInstance().QueryImeExtInfos(userId, extInfos);
1023     if (!ret || extInfos.empty()) {
1024         return ErrorCode::ERROR_PACKAGE_MANAGER;
1025     }
1026     std::vector<ExtensionAbilityInfo> tempExtInfos;
1027     for (const auto &extInfo : extInfos) {
1028         if (IsTempInputMethod(extInfo)) {
1029             continue;
1030         }
1031         if (extInfo.bundleName == bundleName) {
1032             tempExtInfos.push_back(extInfo);
1033         }
1034     }
1035     return GetFullImeInfo(userId, tempExtInfos, imeInfo);
1036 }
1037 
GetFullImeInfo( int32_t userId, const std::vector<OHOS::AppExecFwk::ExtensionAbilityInfo> &extInfos, FullImeInfo &imeInfo)1038 int32_t ImeInfoInquirer::GetFullImeInfo(
1039     int32_t userId, const std::vector<OHOS::AppExecFwk::ExtensionAbilityInfo> &extInfos, FullImeInfo &imeInfo)
1040 {
1041     if (extInfos.empty()) {
1042         return ErrorCode::ERROR_PACKAGE_MANAGER;
1043     }
1044     imeInfo.isNewIme = IsNewExtInfos(extInfos);
1045     auto ret = imeInfo.isNewIme ? ListInputMethodSubtype(userId, extInfos[0], imeInfo.subProps)
1046                         : ListInputMethodSubtype(userId, extInfos, imeInfo.subProps);
1047     if (ret != ErrorCode::NO_ERROR) {
1048         IMSA_HILOGE("[%{public}d,%{public}s] list Subtype failed!", userId, extInfos[0].bundleName.c_str());
1049         return ret;
1050     }
1051     imeInfo.tokenId = extInfos[0].applicationInfo.accessTokenId;
1052     imeInfo.prop.name = extInfos[0].bundleName;
1053     imeInfo.prop.id = extInfos[0].name;
1054     imeInfo.prop.label = GetTargetString(extInfos[0], ImeTargetString::LABEL, userId);
1055     imeInfo.prop.labelId = extInfos[0].applicationInfo.labelId;
1056     imeInfo.prop.iconId = extInfos[0].applicationInfo.iconId;
1057     BundleInfo bundleInfo;
1058     if (GetBundleInfoByBundleName(userId, imeInfo.prop.name, bundleInfo)) {
1059         imeInfo.appId = bundleInfo.signatureInfo.appIdentifier;
1060         imeInfo.versionCode = bundleInfo.versionCode;
1061     }
1062     return ErrorCode::NO_ERROR;
1063 }
1064 
IsInputMethod(int32_t userId, const std::string &bundleName)1065 bool ImeInfoInquirer::IsInputMethod(int32_t userId, const std::string &bundleName)
1066 {
1067     auto bmg = GetBundleMgr();
1068     if (bmg == nullptr) {
1069         return false;
1070     }
1071     BundleInfo bundleInfo;
1072     auto ret = bmg->GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, userId);
1073     if (!ret) {
1074         return false;
1075     }
1076     for (const auto &extInfo : bundleInfo.extensionInfos) {
1077         if (extInfo.type == ExtensionAbilityType::INPUTMETHOD) {
1078             return true;
1079         }
1080     }
1081     return false;
1082 }
1083 
IsTempInputMethod(const ExtensionAbilityInfo &extInfo)1084 bool ImeInfoInquirer::IsTempInputMethod(const ExtensionAbilityInfo &extInfo)
1085 {
1086     auto iter = std::find_if(extInfo.metadata.begin(), extInfo.metadata.end(),
1087         [](const Metadata &metadata) {
1088             return metadata.name == TEMPORARY_INPUT_METHOD_METADATA_NAME;
1089         });
1090     return iter != extInfo.metadata.end();
1091 }
1092 
GetRunningIme(int32_t userId)1093 std::vector<std::string> ImeInfoInquirer::GetRunningIme(int32_t userId)
1094 {
1095     std::vector<std::string> bundleNames;
1096     std::vector<RunningProcessInfo> infos;
1097     AppMgrClient client;
1098     auto ret = client.GetProcessRunningInfosByUserId(infos, userId);
1099     if (ret != ErrorCode::NO_ERROR) {
1100         IMSA_HILOGE("GetAllRunningProcesses failed, ret: %{public}d!", ret);
1101         return bundleNames;
1102     }
1103     for (const auto &info : infos) {
1104         if (info.extensionType_ == ExtensionAbilityType::INPUTMETHOD && !info.bundleNames.empty()) {
1105             bundleNames.push_back(info.bundleNames[0]);
1106         }
1107     }
1108     return bundleNames;
1109 }
1110 
IsDefaultImeSet(int32_t userId)1111 bool ImeInfoInquirer::IsDefaultImeSet(int32_t userId)
1112 {
1113     return ImeCfgManager::GetInstance().IsDefaultImeSet(userId);
1114 }
1115 
IsRunningIme(int32_t userId, const std::string &bundleName)1116 bool ImeInfoInquirer::IsRunningIme(int32_t userId, const std::string &bundleName)
1117 {
1118     auto bundleNames = GetRunningIme(userId);
1119     auto it = std::find_if(bundleNames.begin(), bundleNames.end(),
1120         [&bundleName](const std::string &bundleNameTemp) { return bundleName == bundleNameTemp; });
1121     return it != bundleNames.end();
1122 }
1123 
GetImeAppId(int32_t userId, const std::string &bundleName, std::string &appId)1124 bool ImeInfoInquirer::GetImeAppId(int32_t userId, const std::string &bundleName, std::string &appId)
1125 {
1126     FullImeInfo imeInfo;
1127     if (FullImeInfoManager::GetInstance().Get(bundleName, userId, imeInfo) && !imeInfo.appId.empty()) {
1128         appId = imeInfo.appId;
1129         return true;
1130     }
1131     BundleInfo bundleInfo;
1132     if (!GetBundleInfoByBundleName(userId, bundleName, bundleInfo)) {
1133         return false;
1134     }
1135     appId = bundleInfo.signatureInfo.appIdentifier;
1136     return !appId.empty();
1137 }
1138 
GetImeVersionCode(int32_t userId, const std::string &bundleName, uint32_t &versionCode)1139 bool ImeInfoInquirer::GetImeVersionCode(int32_t userId, const std::string &bundleName, uint32_t &versionCode)
1140 {
1141     FullImeInfo imeInfo;
1142     if (FullImeInfoManager::GetInstance().Get(bundleName, userId, imeInfo)) {
1143         versionCode = imeInfo.versionCode;
1144         return true;
1145     }
1146     BundleInfo bundleInfo;
1147     if (!GetBundleInfoByBundleName(userId, bundleName, bundleInfo)) {
1148         return false;
1149     }
1150     versionCode = bundleInfo.versionCode;
1151     return true;
1152 }
1153 
GetBundleInfoByBundleName( int32_t userId, const std::string &bundleName, AppExecFwk::BundleInfo &bundleInfo)1154 bool ImeInfoInquirer::GetBundleInfoByBundleName(
1155     int32_t userId, const std::string &bundleName, AppExecFwk::BundleInfo &bundleInfo)
1156 {
1157     auto bundleMgr = GetBundleMgr();
1158     if (bundleMgr == nullptr) {
1159         IMSA_HILOGE("failed to get bundleMgr!");
1160         return false;
1161     }
1162     auto ret = bundleMgr->GetBundleInfo(
1163         bundleName, static_cast<int32_t>(GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_SIGNATURE_INFO), bundleInfo, userId);
1164     if (!ret) {
1165         IMSA_HILOGE("failed to get bundle info");
1166         return false;
1167     }
1168     return true;
1169 }
1170 
GetTargetString( const AppExecFwk::ExtensionAbilityInfo &extension, ImeTargetString target, int32_t userId)1171 std::string ImeInfoInquirer::GetTargetString(
1172     const AppExecFwk::ExtensionAbilityInfo &extension, ImeTargetString target, int32_t userId)
1173 {
1174     if (target == ImeTargetString::LABEL) {
1175         if (extension.labelId != DEFAULT_BMS_VALUE) {
1176             return GetStringById(extension.bundleName, extension.moduleName, extension.labelId, userId);
1177         }
1178         IMSA_HILOGD("Extension label is empty, get application label");
1179         return GetStringById(extension.bundleName, extension.applicationInfo.labelResource.moduleName,
1180             extension.applicationInfo.labelResource.id, userId);
1181     }
1182     if (target == ImeTargetString::DESCRIPTION) {
1183         if (extension.descriptionId != DEFAULT_BMS_VALUE) {
1184             return GetStringById(extension.bundleName, extension.moduleName, extension.descriptionId, userId);
1185         }
1186         IMSA_HILOGD("extension description is empty, get application description");
1187         return GetStringById(extension.bundleName, extension.applicationInfo.descriptionResource.moduleName,
1188             extension.applicationInfo.descriptionResource.id, userId);
1189     }
1190     IMSA_HILOGD("No match target string");
1191     return "";
1192 }
1193 } // namespace MiscServices
1194 } // namespace OHOS