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 "enable_ime_data_parser.h"
17
18 #include "ime_info_inquirer.h"
19 #include "iservice_registry.h"
20 #include "nlohmann/json.hpp"
21 #include "settings_data_utils.h"
22 #include "system_ability_definition.h"
23
24 namespace OHOS {
25 namespace MiscServices {
26 using json = nlohmann::json;
27 std::mutex EnableImeDataParser::instanceMutex_;
28 sptr<EnableImeDataParser> EnableImeDataParser::instance_ = nullptr;
~EnableImeDataParser()29 EnableImeDataParser::~EnableImeDataParser()
30 {
31 }
32
GetInstance()33 sptr<EnableImeDataParser> EnableImeDataParser::GetInstance()
34 {
35 if (instance_ == nullptr) {
36 std::lock_guard<std::mutex> autoLock(instanceMutex_);
37 if (instance_ == nullptr) {
38 IMSA_HILOGI("GetInstance need new EnableImeDataParser");
39 instance_ = new (std::nothrow) EnableImeDataParser();
40 if (instance_ == nullptr) {
41 IMSA_HILOGI("instance is nullptr.");
42 return instance_;
43 }
44 }
45 }
46 return instance_;
47 }
48
Initialize(const int32_t userId)49 int32_t EnableImeDataParser::Initialize(const int32_t userId)
50 {
51 currrentUserId_ = userId;
52 enableList_.insert({ std::string(ENABLE_IME), {} });
53 enableList_.insert({ std::string(ENABLE_KEYBOARD), {} });
54
55 if (GetEnableData(ENABLE_IME, enableList_[std::string(ENABLE_IME)], userId) != ErrorCode::NO_ERROR) {
56 IMSA_HILOGW("get enable ime list failed");
57 }
58 if (GetEnableData(ENABLE_KEYBOARD, enableList_[std::string(ENABLE_KEYBOARD)], userId) != ErrorCode::NO_ERROR) {
59 IMSA_HILOGW("get enable keyboard list failed");
60 }
61 GetDefaultIme();
62 return ErrorCode::NO_ERROR;
63 }
64
OnUserChanged(const int32_t targetUserId)65 void EnableImeDataParser::OnUserChanged(const int32_t targetUserId)
66 {
67 std::lock_guard<std::mutex> autoLock(listMutex_);
68 IMSA_HILOGD("Current userId %{public}d, switch to %{public}d", currrentUserId_, targetUserId);
69 currrentUserId_ = targetUserId;
70 if (GetEnableData(ENABLE_IME, enableList_[std::string(ENABLE_IME)], targetUserId) != ErrorCode::NO_ERROR
71 || GetEnableData(ENABLE_KEYBOARD, enableList_[std::string(ENABLE_KEYBOARD)], targetUserId)
72 != ErrorCode::NO_ERROR) {
73 IMSA_HILOGE("get enable list failed.");
74 return;
75 }
76 }
77
CheckNeedSwitch(const std::string & key,SwitchInfo & switchInfo,const int32_t userId)78 bool EnableImeDataParser::CheckNeedSwitch(const std::string &key, SwitchInfo &switchInfo, const int32_t userId)
79 {
80 IMSA_HILOGD("Run in, data changed.");
81 auto currentIme = ImeInfoInquirer::GetInstance().GetCurrentInputMethod(userId);
82 auto defaultIme = GetDefaultIme();
83 switchInfo.bundleName = defaultIme->name;
84 switchInfo.subName = "";
85 if (key == std::string(ENABLE_IME)) {
86 if (currentIme->name == defaultIme->name) {
87 GetEnableData(key, enableList_[key], userId);
88 IMSA_HILOGD("Current ime is default, do not need switch ime.");
89 return false;
90 }
91 return CheckTargetEnableName(key, currentIme->name, switchInfo.bundleName, userId);
92 } else if (key == std::string(ENABLE_KEYBOARD)) {
93 if (currentIme->name != defaultIme->name || currentIme->id == defaultIme->id) {
94 IMSA_HILOGD("Current ime is not default or id is default.");
95 GetEnableData(key, enableList_[key], userId);
96 return false;
97 }
98 switchInfo.subName = defaultIme->id;
99 return CheckTargetEnableName(key, currentIme->id, switchInfo.subName, userId);
100 }
101 IMSA_HILOGW("Invalid key! key: %{public}s", key.c_str());
102 return false;
103 }
104
CheckNeedSwitch(const SwitchInfo & info,const int32_t userId)105 bool EnableImeDataParser::CheckNeedSwitch(const SwitchInfo &info, const int32_t userId)
106 {
107 IMSA_HILOGD("Current userId %{public}d, target userId %{public}d, check bundleName %{public}s", currrentUserId_,
108 userId, info.bundleName.c_str());
109 if (info.bundleName == GetDefaultIme()->name) {
110 IMSA_HILOGD("Default ime, permit to switch");
111 return true;
112 }
113 IMSA_HILOGD("Check ime.");
114 std::vector<std::string> enableVec;
115 int32_t ret = GetEnableData(ENABLE_IME, enableVec, userId);
116 if (ret != ErrorCode::NO_ERROR || enableVec.empty()) {
117 IMSA_HILOGD("Get enable list failed, or enable list is empty.");
118 return false;
119 }
120
121 auto iter = std::find_if(
122 enableVec.begin(), enableVec.end(), [&info](const std::string &ime) { return info.bundleName == ime; });
123 if (iter != enableVec.end()) {
124 IMSA_HILOGD("In enable list.");
125 return true;
126 }
127 return false;
128 }
129
CheckTargetEnableName(const std::string & key,const std::string & targetName,std::string & nextIme,const int32_t userId)130 bool EnableImeDataParser::CheckTargetEnableName(
131 const std::string &key, const std::string &targetName, std::string &nextIme, const int32_t userId)
132 {
133 IMSA_HILOGD("Run in.");
134 std::vector<std::string> enableVec;
135 int32_t ret = GetEnableData(key, enableVec, userId);
136 if (ret != ErrorCode::NO_ERROR) {
137 IMSA_HILOGE("Get enable list abnormal.");
138 return false;
139 }
140
141 if (enableVec.empty()) {
142 IMSA_HILOGE("Enable empty, switch default ime.");
143 return true;
144 }
145 std::lock_guard<std::mutex> autoLock(listMutex_);
146 auto iter = std::find_if(
147 enableVec.begin(), enableVec.end(), [&targetName](const std::string &ime) { return ime == targetName; });
148 if (iter != enableVec.end()) {
149 IMSA_HILOGD("Enable list has current ime, do not need switch.");
150 enableList_[key].assign(enableVec.begin(), enableVec.end());
151 return false;
152 }
153
154 auto it = std::find_if(enableList_[key].begin(), enableList_[key].end(),
155 [&targetName](const std::string &ime) { return ime == targetName; });
156 if (it == enableList_[key].end()) {
157 enableList_[key].assign(enableVec.begin(), enableVec.end());
158 return true;
159 }
160
161 std::rotate(enableList_[key].begin(), it, enableList_[key].end());
162 auto result =
163 std::find_first_of(enableList_[key].begin(), enableList_[key].end(), enableVec.begin(), enableVec.end());
164 if (result != enableList_[key].end()) {
165 IMSA_HILOGD("Found the next cached ime in enable ime list.");
166 nextIme = *result;
167 }
168 enableList_[key].assign(enableVec.begin(), enableVec.end());
169 return true;
170 }
171
GetEnableData(const std::string & key,std::vector<std::string> & enableVec,const int32_t userId)172 int32_t EnableImeDataParser::GetEnableData(
173 const std::string &key, std::vector<std::string> &enableVec, const int32_t userId)
174 {
175 if (key != std::string(ENABLE_IME) && key != std::string(ENABLE_KEYBOARD)) {
176 IMSA_HILOGD("Invalid key: %{public}s.", key.c_str());
177 return ErrorCode::ERROR_ENABLE_IME;
178 }
179
180 IMSA_HILOGD("userId: %{public}d, key: %{public}s.", userId, key.c_str());
181 std::string valueStr;
182 int32_t ret = SettingsDataUtils::GetInstance()->GetStringValue(key, valueStr);
183 if (ret == ErrorCode::ERROR_KEYWORD_NOT_FOUND) {
184 IMSA_HILOGW("No keyword exist");
185 enableVec.clear();
186 return ErrorCode::NO_ERROR;
187 }
188 if (ret != ErrorCode::NO_ERROR || valueStr.empty()) {
189 IMSA_HILOGW("Get value failed, or valueStr is empty");
190 return ErrorCode::ERROR_ENABLE_IME;
191 }
192
193 if (!ParseJsonData(key, valueStr, enableVec, userId)) {
194 IMSA_HILOGE("valueStr is empty");
195 return ErrorCode::ERROR_ENABLE_IME;
196 }
197 return ErrorCode::NO_ERROR;
198 }
199
ParseJsonData(const std::string & key,const std::string & valueStr,std::vector<std::string> & enableVec,const int32_t userId)200 bool EnableImeDataParser::ParseJsonData(
201 const std::string &key, const std::string &valueStr, std::vector<std::string> &enableVec, const int32_t userId)
202 {
203 IMSA_HILOGD("valueStr: %{public}s.", valueStr.c_str());
204 json jsonEnableData = json::parse(valueStr.c_str());
205 if (jsonEnableData.is_null() || jsonEnableData.is_discarded()) {
206 IMSA_HILOGE("json parse failed.");
207 return false;
208 }
209 std::string listName = GetJsonListName(key);
210 if (listName.empty()) {
211 IMSA_HILOGE("Get list name failed.");
212 return false;
213 }
214
215 if (!jsonEnableData.contains(listName) || !jsonEnableData[listName].is_object()) {
216 IMSA_HILOGE("listName not find or abnormal");
217 return false;
218 }
219
220 std::string id = std::to_string(userId);
221 if (!jsonEnableData[listName].contains(id) || !jsonEnableData[listName][id].is_array()) {
222 IMSA_HILOGE("user id not find or abnormal");
223 return false;
224 }
225 std::vector<std::string> enableVecTemp;
226 for (const auto &bundleName : jsonEnableData[listName][id]) {
227 IMSA_HILOGD("enable ime string: %{public}s", std::string(bundleName).c_str());
228 enableVecTemp.push_back(bundleName);
229 }
230 enableVec.assign(enableVecTemp.begin(), enableVecTemp.end());
231 return true;
232 }
233
GetJsonListName(const std::string & key)234 const std::string EnableImeDataParser::GetJsonListName(const std::string &key)
235 {
236 if (key == std::string(ENABLE_IME)) {
237 return "enableImeList";
238 } else if (key == std::string(ENABLE_KEYBOARD)) {
239 return "enableKeyboardList";
240 }
241 return "";
242 }
243
GetDefaultIme()244 std::shared_ptr<Property> EnableImeDataParser::GetDefaultIme()
245 {
246 std::lock_guard<std::mutex> lock(defaultImeMutex_);
247 if (defaultImeInfo_ == nullptr) {
248 defaultImeInfo_ = std::make_shared<Property>();
249 }
250 if (!defaultImeInfo_->name.empty() && !defaultImeInfo_->id.empty()) {
251 IMSA_HILOGD("defaultImeInfo_ has cached defaultime: %{public}s", defaultImeInfo_->name.c_str());
252 return defaultImeInfo_;
253 }
254
255 auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultImeCfgProp();
256 if (defaultIme == nullptr) {
257 IMSA_HILOGE("GetDefaultImeCfgProp return nullptr");
258 return defaultImeInfo_;
259 }
260 defaultImeInfo_->name = defaultIme->name;
261 defaultImeInfo_->id = defaultIme->id;
262 return defaultImeInfo_;
263 }
264 } // namespace MiscServices
265 } // namespace OHOS