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 "serializable.h"
21 #include "settings_data_utils.h"
22 #include "system_ability_definition.h"
23
24 namespace OHOS {
25 namespace MiscServices {
26 std::mutex EnableImeDataParser::instanceMutex_;
27 sptr<EnableImeDataParser> EnableImeDataParser::instance_ = nullptr;
~EnableImeDataParser()28 EnableImeDataParser::~EnableImeDataParser()
29 {
30 }
31
GetInstance()32 sptr<EnableImeDataParser> EnableImeDataParser::GetInstance()
33 {
34 if (instance_ == nullptr) {
35 std::lock_guard<std::mutex> autoLock(instanceMutex_);
36 if (instance_ == nullptr) {
37 IMSA_HILOGI("need to create instance.");
38 instance_ = new (std::nothrow) EnableImeDataParser();
39 if (instance_ == nullptr) {
40 IMSA_HILOGE("instance is nullptr!");
41 return instance_;
42 }
43 }
44 }
45 return instance_;
46 }
47
Initialize(const int32_t userId)48 int32_t EnableImeDataParser::Initialize(const int32_t userId)
49 {
50 currentUserId_ = userId;
51 {
52 std::lock_guard<std::mutex> autoLock(listMutex_);
53 enableList_.insert({ std::string(ENABLE_IME), {} });
54 enableList_.insert({ std::string(ENABLE_KEYBOARD), {} });
55 }
56 UpdateEnableData(userId, ENABLE_IME);
57 UpdateEnableData(userId, ENABLE_KEYBOARD);
58 GetDefaultIme();
59 return ErrorCode::NO_ERROR;
60 }
61
OnUserChanged(const int32_t targetUserId)62 void EnableImeDataParser::OnUserChanged(const int32_t targetUserId)
63 {
64 currentUserId_ = targetUserId;
65 UpdateEnableData(targetUserId, ENABLE_IME);
66 UpdateEnableData(targetUserId, ENABLE_KEYBOARD);
67 }
68
CheckNeedSwitch(const std::string & key,SwitchInfo & switchInfo,const int32_t userId)69 bool EnableImeDataParser::CheckNeedSwitch(const std::string &key, SwitchInfo &switchInfo, const int32_t userId)
70 {
71 IMSA_HILOGD("start, data changed.");
72 auto currentIme = ImeInfoInquirer::GetInstance().GetCurrentInputMethod(userId);
73 auto defaultIme = GetDefaultIme();
74 if (defaultIme == nullptr) {
75 IMSA_HILOGE("defaultIme is nullptr!");
76 return false;
77 }
78 switchInfo.bundleName = defaultIme->name;
79 switchInfo.subName = "";
80 if (currentIme == nullptr) {
81 IMSA_HILOGE("currentIme is nullptr!");
82 return true;
83 }
84 if (key == std::string(ENABLE_IME)) {
85 if (currentIme->name == defaultIme->name) {
86 std::lock_guard<std::mutex> autoLock(listMutex_);
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 std::lock_guard<std::mutex> autoLock(listMutex_);
96 GetEnableData(key, enableList_[key], userId);
97 return false;
98 }
99 switchInfo.subName = defaultIme->id;
100 return CheckTargetEnableName(key, currentIme->id, switchInfo.subName, userId);
101 }
102 IMSA_HILOGW("invalid key: %{public}s.", key.c_str());
103 return false;
104 }
105
CheckNeedSwitch(const SwitchInfo & info,const int32_t userId)106 bool EnableImeDataParser::CheckNeedSwitch(const SwitchInfo &info, const int32_t userId)
107 {
108 IMSA_HILOGD("current userId: %{public}d, target userId: %{public}d, check bundleName: %{public}s", currentUserId_,
109 userId, info.bundleName.c_str());
110 if (info.bundleName == GetDefaultIme()->name) {
111 IMSA_HILOGD("default ime, permit to switch");
112 return true;
113 }
114 IMSA_HILOGD("check ime.");
115 std::vector<std::string> tempVec;
116 int32_t tempRet = GetEnableData(TEMP_IME, tempVec, userId);
117 if (tempRet != ErrorCode::NO_ERROR || tempVec.empty()) {
118 IMSA_HILOGD("get tempVec list failed, or tempVec list is empty.");
119 } else {
120 auto iter = std::find_if(
121 tempVec.begin(), tempVec.end(), [&info](const std::string &ime) { return info.bundleName == ime; });
122 if (iter != tempVec.end()) {
123 IMSA_HILOGD("In tempVec list.");
124 return true;
125 }
126 }
127 std::vector<std::string> enableVec;
128 int32_t ret = GetEnableData(ENABLE_IME, enableVec, userId);
129 if (ret != ErrorCode::NO_ERROR || enableVec.empty()) {
130 IMSA_HILOGD("get enable list failed, or enable list is empty.");
131 return false;
132 }
133
134 auto iter = std::find_if(
135 enableVec.begin(), enableVec.end(), [&info](const std::string &ime) { return info.bundleName == ime; });
136 if (iter != enableVec.end()) {
137 IMSA_HILOGD("in enable list.");
138 return true;
139 }
140 return false;
141 }
142
CheckTargetEnableName(const std::string & key,const std::string & targetName,std::string & nextIme,const int32_t userId)143 bool EnableImeDataParser::CheckTargetEnableName(
144 const std::string &key, const std::string &targetName, std::string &nextIme, const int32_t userId)
145 {
146 IMSA_HILOGD("start.");
147 std::vector<std::string> enableVec;
148 int32_t ret = GetEnableData(key, enableVec, userId);
149 if (ret != ErrorCode::NO_ERROR) {
150 IMSA_HILOGE("get enable list abnormal.");
151 return false;
152 }
153
154 if (enableVec.empty()) {
155 IMSA_HILOGE("enable empty, switch default ime.");
156 return true;
157 }
158 std::lock_guard<std::mutex> autoLock(listMutex_);
159 auto iter = std::find_if(
160 enableVec.begin(), enableVec.end(), [&targetName](const std::string &ime) { return ime == targetName; });
161 if (iter != enableVec.end()) {
162 IMSA_HILOGD("enable list has current ime, do not need switch.");
163 enableList_[key].assign(enableVec.begin(), enableVec.end());
164 return false;
165 }
166
167 auto it = std::find_if(enableList_[key].begin(), enableList_[key].end(),
168 [&targetName](const std::string &ime) { return ime == targetName; });
169 if (it == enableList_[key].end()) {
170 enableList_[key].assign(enableVec.begin(), enableVec.end());
171 return true;
172 }
173
174 std::rotate(enableList_[key].begin(), it, enableList_[key].end());
175 auto result =
176 std::find_first_of(enableList_[key].begin(), enableList_[key].end(), enableVec.begin(), enableVec.end());
177 if (result != enableList_[key].end()) {
178 IMSA_HILOGD("found the next cached ime in enable ime list.");
179 nextIme = *result;
180 }
181 enableList_[key].assign(enableVec.begin(), enableVec.end());
182 return true;
183 }
184
CoverGlobalTable(const std::string & key,std::string & valueStr)185 void EnableImeDataParser::CoverGlobalTable(const std::string &key, std::string &valueStr)
186 {
187 SettingsDataUtils::GetInstance()->SetStringValue(SETTING_URI_PROXY, key, valueStr);
188 }
189
GetUserEnableTable(int32_t userId,const std::string & key)190 std::string EnableImeDataParser::GetUserEnableTable(int32_t userId, const std::string &key)
191 {
192 std::string valueStr;
193 int32_t ret = SettingsDataUtils::GetInstance()->GetStringValue(
194 SETTINGS_USER_DATA_URI + std::to_string(userId) + "?Proxy=true", key, valueStr);
195 IMSA_HILOGI("get user enable table, userId = %{public}d, ret = %{public}d, valurStr = %{public}s",
196 userId, ret, valueStr.c_str());
197 if (valueStr.empty()) {
198 auto defaultIme = GetDefaultIme();
199 if (defaultIme != nullptr) {
200 valueStr =
201 "{\"enableImeList\" : {\"" + std::to_string(userId) + "\" : [\"" + defaultIme->name + "\"]}}";
202 }
203 }
204 return valueStr;
205 }
206
GetEanbleIme(int32_t userId,const std::string & key,const std::string & globalStr)207 std::string EnableImeDataParser::GetEanbleIme(int32_t userId, const std::string &key, const std::string &globalStr)
208 {
209 std::string enableStr = globalStr;
210 std::string globaleUserId;
211 if (enableStr.empty()) {
212 enableStr = GetUserEnableTable(currentUserId_, key);
213 CoverGlobalTable(key, enableStr);
214 globaleUserId = std::to_string(currentUserId_);
215 } else {
216 globaleUserId = GetGlobalTableUserId(enableStr);
217 }
218 SettingsDataUtils::GetInstance()->SetStringValue(SETTINGS_USER_DATA_URI + globaleUserId + "?Proxy=true",
219 key, enableStr);
220 if (globaleUserId != std::to_string(currentUserId_)) {
221 enableStr = GetUserEnableTable(currentUserId_, key);
222 CoverGlobalTable(key, enableStr);
223 }
224 if (currentUserId_ != userId) {
225 enableStr = GetUserEnableTable(userId, key);
226 }
227 return enableStr;
228 }
229
GetEnableData(const std::string & key,std::vector<std::string> & enableVec,const int32_t userId)230 int32_t EnableImeDataParser::GetEnableData(
231 const std::string &key, std::vector<std::string> &enableVec, const int32_t userId)
232 {
233 if (key != std::string(ENABLE_IME) && key != std::string(ENABLE_KEYBOARD) && key != std::string(TEMP_IME)) {
234 IMSA_HILOGD("invalid key: %{public}s.", key.c_str());
235 return ErrorCode::ERROR_ENABLE_IME;
236 }
237
238 IMSA_HILOGD("userId: %{public}d, key: %{public}s.", userId, key.c_str());
239 std::string valueStr;
240 int32_t ret = SettingsDataUtils::GetInstance()->GetStringValue(SETTING_URI_PROXY, key, valueStr);
241 if (ret == ErrorCode::ERROR_KEYWORD_NOT_FOUND) {
242 IMSA_HILOGW("no keyword exist");
243 enableVec.clear();
244 return ErrorCode::NO_ERROR;
245 }
246 if (key != ENABLE_IME && (ret != ErrorCode::NO_ERROR || valueStr.empty())) {
247 IMSA_HILOGW("get value failed, or valueStr is empty.");
248 return ErrorCode::ERROR_ENABLE_IME;
249 }
250 auto parseRet = false;
251 if (key == ENABLE_IME) {
252 valueStr = GetEanbleIme(userId, key, valueStr);
253 if (valueStr.empty()) {
254 IMSA_HILOGW("valueStr is empty, userId = %{public}d", userId);
255 return ErrorCode::NO_ERROR;
256 }
257 parseRet = ParseEnableIme(valueStr, userId, enableVec);
258 }
259 if (key == ENABLE_KEYBOARD) {
260 parseRet = ParseEnableKeyboard(valueStr, userId, enableVec);
261 }
262 if (key == TEMP_IME) {
263 parseRet = ParseTempIme(valueStr, userId, enableVec);
264 }
265 return parseRet ? ErrorCode::NO_ERROR : ErrorCode::ERROR_ENABLE_IME;
266 }
267
GetGlobalTableUserId(const std::string & valueStr)268 std::string EnableImeDataParser::GetGlobalTableUserId(const std::string &valueStr)
269 {
270 auto root = cJSON_Parse(valueStr.c_str());
271 auto subNode = Serializable::GetSubNode(root, "enableImeList");
272 if (subNode == nullptr || cJSON_IsObject(subNode)) {
273 IMSA_HILOGW("subNode is null or not object");
274 return "";
275 }
276 if (subNode->child == nullptr) {
277 IMSA_HILOGW("subNode has not child");
278 return "";
279 }
280 return subNode->child->string;
281 }
282
ParseTempIme(const std::string & valueStr,int32_t userId,std::vector<std::string> & tempVector)283 bool EnableImeDataParser::ParseTempIme(const std::string &valueStr, int32_t userId,
284 std::vector<std::string> &tempVector)
285 {
286 TempImeCfg tempIme;
287 tempIme.tempImeList.userId = std::to_string(userId);
288 auto ret = tempIme.Unmarshall(valueStr);
289 if (!ret) {
290 return ret;
291 }
292 tempVector = tempIme.tempImeList.identities;
293 return true;
294 }
295
ParseEnableIme(const std::string & valueStr,int32_t userId,std::vector<std::string> & enableVec)296 bool EnableImeDataParser::ParseEnableIme(
297 const std::string &valueStr, int32_t userId, std::vector<std::string> &enableVec)
298 {
299 EnableImeCfg enableIme;
300 enableIme.userImeCfg.userId = std::to_string(userId);
301 auto ret = enableIme.Unmarshall(valueStr);
302 if (!ret) {
303 return ret;
304 }
305 enableVec = enableIme.userImeCfg.identities;
306 return true;
307 }
308
ParseEnableKeyboard(const std::string & valueStr,int32_t userId,std::vector<std::string> & enableVec)309 bool EnableImeDataParser::ParseEnableKeyboard(
310 const std::string &valueStr, int32_t userId, std::vector<std::string> &enableVec)
311 {
312 EnableKeyBoardCfg enableKeyboard;
313 enableKeyboard.userImeCfg.userId = std::to_string(userId);
314 auto ret = enableKeyboard.Unmarshall(valueStr);
315 if (!ret) {
316 return ret;
317 }
318 enableVec = enableKeyboard.userImeCfg.identities;
319 return true;
320 }
321
GetDefaultIme()322 std::shared_ptr<Property> EnableImeDataParser::GetDefaultIme()
323 {
324 std::lock_guard<std::mutex> lock(defaultImeMutex_);
325 if (defaultImeInfo_ == nullptr) {
326 defaultImeInfo_ = std::make_shared<Property>();
327 }
328 if (!defaultImeInfo_->name.empty() && !defaultImeInfo_->id.empty()) {
329 IMSA_HILOGD("defaultImeInfo_ has cached default time: %{public}s.", defaultImeInfo_->name.c_str());
330 return defaultImeInfo_;
331 }
332
333 auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultImeCfgProp();
334 if (defaultIme == nullptr) {
335 IMSA_HILOGE("defaultIme is nullptr!");
336 return defaultImeInfo_;
337 }
338 defaultImeInfo_->name = defaultIme->name;
339 defaultImeInfo_->id = defaultIme->id;
340 return defaultImeInfo_;
341 }
342
OnConfigChanged(int32_t userId,const std::string & key)343 void EnableImeDataParser::OnConfigChanged(int32_t userId, const std::string &key)
344 {
345 UpdateEnableData(userId, key);
346 }
347
UpdateEnableData(int32_t userId,const std::string & key)348 int32_t EnableImeDataParser::UpdateEnableData(int32_t userId, const std::string &key)
349 {
350 std::lock_guard<std::mutex> autoLock(listMutex_);
351 if (key == ENABLE_IME) {
352 isEnableImeInit_ = false;
353 }
354 std::vector<std::string> enableData;
355 IMSA_HILOGD("update userId: %{public}d %{public}s", userId, key.c_str());
356 auto ret = GetEnableData(key, enableData, userId);
357 if (ret != ErrorCode::NO_ERROR) {
358 IMSA_HILOGE("userId: %{public}d get enable %{public}s list failed!", userId, key.c_str());
359 return ret;
360 }
361 enableList_.insert_or_assign(key, enableData);
362 if (key == ENABLE_IME) {
363 isEnableImeInit_ = true;
364 }
365 return ErrorCode::NO_ERROR;
366 }
367
GetEnableIme(int32_t userId,std::vector<std::string> & enableVec)368 int32_t EnableImeDataParser::GetEnableIme(int32_t userId, std::vector<std::string> &enableVec)
369 {
370 if (userId != currentUserId_) {
371 return GetEnableData(ENABLE_IME, enableVec, userId);
372 }
373 auto ret = GetEnableImeFromCache(enableVec);
374 if (ret == ErrorCode::NO_ERROR) {
375 return ErrorCode::NO_ERROR;
376 }
377 ret = UpdateEnableData(userId, ENABLE_IME);
378 if (ret != ErrorCode::NO_ERROR) {
379 return ret;
380 }
381 return GetEnableImeFromCache(enableVec);
382 }
383
GetEnableImeFromCache(std::vector<std::string> & enableVec)384 int32_t EnableImeDataParser::GetEnableImeFromCache(std::vector<std::string> &enableVec)
385 {
386 std::lock_guard<std::mutex> autoLock(listMutex_);
387 if (isEnableImeInit_) {
388 auto it = enableList_.find(ENABLE_IME);
389 if (it != enableList_.end()) {
390 IMSA_HILOGD("GetEnableIme from cache.");
391 enableVec = it->second;
392 return ErrorCode::NO_ERROR;
393 }
394 }
395 return ErrorCode::ERROR_ENABLE_IME;
396 }
397 } // namespace MiscServices
398 } // namespace OHOS