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
41namespace OHOS {
42namespace MiscServices {
43namespace {
44using namespace OHOS::AppExecFwk;
45using namespace Global::Resource;
46using namespace OHOS::AAFwk;
47constexpr const char *SUBTYPE_PROFILE_METADATA_NAME = "ohos.extension.input_method";
48constexpr const char *TEMPORARY_INPUT_METHOD_METADATA_NAME = "ohos.extension.temporary_input_method";
49constexpr uint32_t SUBTYPE_PROFILE_NUM = 1;
50constexpr const char *DEFAULT_IME_KEY = "persist.sys.default_ime";
51constexpr int32_t CONFIG_LEN = 128;
52constexpr uint32_t DEFAULT_BMS_VALUE = 0;
53} // namespace
54ImeInfoInquirer &ImeInfoInquirer::GetInstance()
55{
56    static ImeInfoInquirer instance;
57    return instance;
58}
59
60void ImeInfoInquirer::InitSystemConfig()
61{
62    auto ret = SysCfgParser::ParseSystemConfig(systemConfig_);
63    if (!ret) {
64        IMSA_HILOGE("parse systemConfig failed!");
65        return;
66    }
67}
68
69bool ImeInfoInquirer::IsEnableInputMethod()
70{
71    return systemConfig_.enableInputMethodFeature;
72}
73
74bool ImeInfoInquirer::IsEnableSecurityMode()
75{
76    return systemConfig_.enableFullExperienceFeature;
77}
78
79bool 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
94int32_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
115std::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
124std::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
157std::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
203std::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
229std::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
254int32_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
270int32_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
305int32_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
332int32_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
362int32_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
390int32_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
413int32_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
420bool 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
431int32_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
459int32_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
481int32_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
526int32_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
578int32_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
607void 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
627std::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
634SubProperty 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
657std::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
675std::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
692std::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
729bool 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
747std::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
768int32_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
794int32_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
825std::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
849ImeNativeCfg 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
870sptr<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
886std::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
921bool 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
930std::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
943std::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
967int32_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
987int32_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
1019int32_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
1038int32_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
1065bool 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
1084bool 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
1093std::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
1111bool ImeInfoInquirer::IsDefaultImeSet(int32_t userId)
1112{
1113    return ImeCfgManager::GetInstance().IsDefaultImeSet(userId);
1114}
1115
1116bool 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
1124bool 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
1139bool 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
1154bool 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
1171std::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