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 [¤tImeBundle](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 [¤tImeCfg](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 [¤tIme](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 [¤tIme](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