1 /*
2 * Copyright (c) 2022 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_cfg_manager.h"
17
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22
23 #include <algorithm>
24 #include <cstdio>
25 #include <ios>
26 #include <string>
27
28 #include "file_ex.h"
29 #include "global.h"
30 namespace OHOS {
31 namespace MiscServices {
32 namespace {
33 constexpr const char *IME_CFG_DIR = "/data/service/el1/public/imf/ime_cfg";
34 constexpr const char *IME_CFG_FILE_PATH = "/data/service/el1/public/imf/ime_cfg/ime_cfg.json";
35 static constexpr int32_t SUCCESS = 0;
36 static constexpr uint32_t MAX_FILE_LENGTH = 10000;
37 using json = nlohmann::json;
38 } // namespace
GetInstance()39 ImeCfgManager &ImeCfgManager::GetInstance()
40 {
41 static ImeCfgManager instance;
42 return instance;
43 }
44
Init()45 void ImeCfgManager::Init()
46 {
47 std::string path(IME_CFG_DIR);
48 if (CreateCachePath(path, S_IRWXU) != SUCCESS) {
49 IMSA_HILOGE("CreateCachePath failed");
50 return;
51 }
52 ReadImeCfgFile();
53 }
54
ReadImeCfgFile()55 void ImeCfgManager::ReadImeCfgFile()
56 {
57 json jsonConfigs;
58 bool ret = ReadCacheFile(IME_CFG_FILE_PATH, jsonConfigs);
59 if (!ret) {
60 IMSA_HILOGE("ReadJsonFile failed");
61 return;
62 }
63 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
64 FromJson(jsonConfigs, imeConfigs_);
65 }
66
WriteImeCfgFile()67 void ImeCfgManager::WriteImeCfgFile()
68 {
69 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
70 json jsonConfigs;
71 ToJson(jsonConfigs, imeConfigs_);
72 if (!WriteCacheFile(IME_CFG_FILE_PATH, jsonConfigs)) {
73 IMSA_HILOGE("WriteJsonFile failed");
74 }
75 }
76
AddImeCfg(const ImePersistCfg & cfg)77 void ImeCfgManager::AddImeCfg(const ImePersistCfg &cfg)
78 {
79 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
80 imeConfigs_.push_back(cfg);
81 WriteImeCfgFile();
82 }
83
ModifyImeCfg(const ImePersistCfg & cfg)84 void ImeCfgManager::ModifyImeCfg(const ImePersistCfg &cfg)
85 {
86 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
87 auto it = std::find_if(imeConfigs_.begin(), imeConfigs_.end(),
88 [cfg](const ImePersistCfg &imeCfg) { return imeCfg.userId == cfg.userId && !cfg.currentIme.empty(); });
89 if (it != imeConfigs_.end()) {
90 *it = cfg;
91 }
92
93 WriteImeCfgFile();
94 }
95
DeleteImeCfg(int32_t userId)96 void ImeCfgManager::DeleteImeCfg(int32_t userId)
97 {
98 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
99 for (auto iter = imeConfigs_.begin(); iter != imeConfigs_.end(); iter++) {
100 if (iter->userId == userId) {
101 imeConfigs_.erase(iter);
102 break;
103 }
104 }
105 WriteImeCfgFile();
106 }
107
GetImeCfg(int32_t userId)108 ImePersistCfg ImeCfgManager::GetImeCfg(int32_t userId)
109 {
110 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
111 auto it = std::find_if(
112 imeConfigs_.begin(), imeConfigs_.end(), [userId](const ImePersistCfg &cfg) { return cfg.userId == userId; });
113 if (it != imeConfigs_.end()) {
114 return *it;
115 }
116 return {};
117 }
118
GetCurrentImeCfg(int32_t userId)119 std::shared_ptr<ImeNativeCfg> ImeCfgManager::GetCurrentImeCfg(int32_t userId)
120 {
121 auto cfg = GetImeCfg(userId);
122 ImeNativeCfg info;
123 info.subName = cfg.currentSubName;
124 info.imeId = cfg.currentIme;
125 auto pos = info.imeId.find('/');
126 if (pos != std::string::npos && pos + 1 < info.imeId.size()) {
127 info.bundleName = info.imeId.substr(0, pos);
128 info.extName = info.imeId.substr(pos + 1);
129 }
130 return std::make_shared<ImeNativeCfg>(info);
131 }
132
FromJson(const json & jsonConfigs,std::vector<ImePersistCfg> & configs)133 void ImeCfgManager::FromJson(const json &jsonConfigs, std::vector<ImePersistCfg> &configs)
134 {
135 if (!jsonConfigs.contains("imeCfg_list")) {
136 IMSA_HILOGE("imeCfg_list not find");
137 return;
138 }
139 for (auto &jsonCfg : jsonConfigs["imeCfg_list"]) {
140 ImePersistCfg cfg;
141 FromJson(jsonCfg, cfg);
142 configs.push_back(cfg);
143 }
144 }
145
ToJson(json & jsonConfigs,const std::vector<ImePersistCfg> & configs)146 void ImeCfgManager::ToJson(json &jsonConfigs, const std::vector<ImePersistCfg> &configs)
147 {
148 for (auto &cfg : configs) {
149 json jsonCfg;
150 ToJson(jsonCfg, cfg);
151 jsonConfigs["imeCfg_list"].push_back(jsonCfg);
152 }
153 }
154
CreateCachePath(std::string & path,mode_t pathMode)155 int32_t ImeCfgManager::CreateCachePath(std::string &path, mode_t pathMode)
156 {
157 if (IsCachePathExit(path)) {
158 IMSA_HILOGI("dir: %{public}s exist", path.c_str());
159 return SUCCESS;
160 }
161 return mkdir(path.c_str(), pathMode);
162 }
163
IsCachePathExit(std::string & path)164 bool ImeCfgManager::IsCachePathExit(std::string &path)
165 {
166 return access(path.c_str(), F_OK) == SUCCESS;
167 }
168
ReadCacheFile(const std::string & path,json & jsonCfg)169 bool ImeCfgManager::ReadCacheFile(const std::string &path, json &jsonCfg)
170 {
171 auto fd = open(path.c_str(), O_RDONLY);
172 if (fd <= 0) {
173 IMSA_HILOGE("file open failed, fd: %{public}d", fd);
174 return false;
175 }
176 char cfg[MAX_FILE_LENGTH] = { 0 };
177 auto ret = read(fd, cfg, MAX_FILE_LENGTH);
178 if (ret <= 0) {
179 IMSA_HILOGE("file read failed, ret: %{public}zd", ret);
180 close(fd);
181 return false;
182 }
183 close(fd);
184
185 if (cfg[0] == '\0') {
186 IMSA_HILOGE("imeCfg is empty");
187 return false;
188 }
189 jsonCfg = json::parse(cfg, nullptr, false);
190 if (jsonCfg.is_null() || jsonCfg.is_discarded()) {
191 IMSA_HILOGE("json parse failed.");
192 return false;
193 }
194 IMSA_HILOGD("imeCfg json: %{public}s", jsonCfg.dump().c_str());
195 return true;
196 }
197
WriteCacheFile(const std::string & path,const json & jsonCfg)198 bool ImeCfgManager::WriteCacheFile(const std::string &path, const json &jsonCfg)
199 {
200 std::string cfg = jsonCfg.dump();
201 if (cfg.empty()) {
202 IMSA_HILOGE("imeCfg is empty");
203 return false;
204 }
205 IMSA_HILOGD("imeCfg json: %{public}s", cfg.c_str());
206 auto fd = open(path.c_str(), O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, S_IRUSR | S_IWUSR);
207 if (fd <= 0) {
208 IMSA_HILOGE("file open failed, fd: %{public}d", fd);
209 return false;
210 }
211 auto ret = write(fd, cfg.c_str(), cfg.size());
212 if (ret <= 0) {
213 IMSA_HILOGE("file write failed, ret: %{public}zd", ret);
214 close(fd);
215 return false;
216 }
217 close(fd);
218 return true;
219 }
220 } // namespace MiscServices
221 } // namespace OHOS