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 ReadImeCfg();
48 }
49
ReadImeCfg()50 void ImeCfgManager::ReadImeCfg()
51 {
52 std::string path(IME_CFG_FILE_PATH);
53 if (!IsExist(path)) {
54 IMSA_HILOGD("ime cfg file not find");
55 return;
56 }
57 json jsonConfigs;
58 bool ret = Read(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
WriteImeCfg()67 void ImeCfgManager::WriteImeCfg()
68 {
69 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
70 json jsonConfigs;
71 ToJson(jsonConfigs, imeConfigs_);
72
73 std::string path(IME_CFG_DIR);
74 if (!IsExist(path)) {
75 auto ret = Create(path, S_IRWXU);
76 if (ret != SUCCESS) {
77 IMSA_HILOGE("ime cfg dir create failed");
78 return;
79 }
80 }
81 if (!Write(IME_CFG_FILE_PATH, jsonConfigs)) {
82 IMSA_HILOGE("WriteJsonFile failed");
83 }
84 }
85
AddImeCfg(const ImePersistCfg & cfg)86 void ImeCfgManager::AddImeCfg(const ImePersistCfg &cfg)
87 {
88 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
89 imeConfigs_.push_back(cfg);
90 WriteImeCfg();
91 }
92
ModifyImeCfg(const ImePersistCfg & cfg)93 void ImeCfgManager::ModifyImeCfg(const ImePersistCfg &cfg)
94 {
95 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
96 auto it = std::find_if(imeConfigs_.begin(), imeConfigs_.end(),
97 [cfg](const ImePersistCfg &imeCfg) { return imeCfg.userId == cfg.userId && !cfg.currentIme.empty(); });
98 if (it != imeConfigs_.end()) {
99 *it = cfg;
100 }
101
102 WriteImeCfg();
103 }
104
DeleteImeCfg(int32_t userId)105 void ImeCfgManager::DeleteImeCfg(int32_t userId)
106 {
107 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
108 for (auto iter = imeConfigs_.begin(); iter != imeConfigs_.end(); iter++) {
109 if (iter->userId == userId) {
110 imeConfigs_.erase(iter);
111 break;
112 }
113 }
114 WriteImeCfg();
115 }
116
GetImeCfg(int32_t userId)117 ImePersistCfg ImeCfgManager::GetImeCfg(int32_t userId)
118 {
119 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
120 auto it = std::find_if(
121 imeConfigs_.begin(), imeConfigs_.end(), [userId](const ImePersistCfg &cfg) { return cfg.userId == userId; });
122 if (it != imeConfigs_.end()) {
123 return *it;
124 }
125 return {};
126 }
127
GetCurrentImeCfg(int32_t userId)128 std::shared_ptr<ImeNativeCfg> ImeCfgManager::GetCurrentImeCfg(int32_t userId)
129 {
130 auto cfg = GetImeCfg(userId);
131 ImeNativeCfg info;
132 info.subName = cfg.currentSubName;
133 info.imeId = cfg.currentIme;
134 auto pos = info.imeId.find('/');
135 if (pos != std::string::npos && pos + 1 < info.imeId.size()) {
136 info.bundleName = info.imeId.substr(0, pos);
137 info.extName = info.imeId.substr(pos + 1);
138 }
139 return std::make_shared<ImeNativeCfg>(info);
140 }
141
FromJson(const json & jsonConfigs,std::vector<ImePersistCfg> & configs)142 void ImeCfgManager::FromJson(const json &jsonConfigs, std::vector<ImePersistCfg> &configs)
143 {
144 if (!jsonConfigs.contains("imeCfg_list") || !jsonConfigs["imeCfg_list"].is_array()) {
145 IMSA_HILOGE("imeCfg_list not find or abnormal");
146 return;
147 }
148 for (auto &jsonCfg : jsonConfigs["imeCfg_list"]) {
149 ImePersistCfg cfg;
150 FromJson(jsonCfg, cfg);
151 configs.push_back(cfg);
152 }
153 }
154
ToJson(json & jsonConfigs,const std::vector<ImePersistCfg> & configs)155 void ImeCfgManager::ToJson(json &jsonConfigs, const std::vector<ImePersistCfg> &configs)
156 {
157 for (auto &cfg : configs) {
158 json jsonCfg;
159 ToJson(jsonCfg, cfg);
160 jsonConfigs["imeCfg_list"].push_back(jsonCfg);
161 }
162 }
163
Create(std::string & path,mode_t pathMode)164 int32_t ImeCfgManager::Create(std::string &path, mode_t pathMode)
165 {
166 return mkdir(path.c_str(), pathMode);
167 }
168
IsExist(std::string & path)169 bool ImeCfgManager::IsExist(std::string &path)
170 {
171 return access(path.c_str(), F_OK) == SUCCESS;
172 }
173
Read(const std::string & path,json & jsonCfg)174 bool ImeCfgManager::Read(const std::string &path, json &jsonCfg)
175 {
176 auto fd = open(path.c_str(), O_RDONLY);
177 if (fd <= 0) {
178 IMSA_HILOGE("file open failed, fd: %{public}d", fd);
179 return false;
180 }
181 char cfg[MAX_FILE_LENGTH] = { 0 };
182 auto ret = read(fd, cfg, MAX_FILE_LENGTH);
183 if (ret <= 0) {
184 IMSA_HILOGE("file read failed, ret: %{public}zd", ret);
185 close(fd);
186 return false;
187 }
188 close(fd);
189
190 if (cfg[0] == '\0') {
191 IMSA_HILOGE("imeCfg is empty");
192 return false;
193 }
194 jsonCfg = json::parse(cfg, nullptr, false);
195 if (jsonCfg.is_null() || jsonCfg.is_discarded()) {
196 IMSA_HILOGE("json parse failed.");
197 return false;
198 }
199 IMSA_HILOGD("imeCfg json: %{public}s", jsonCfg.dump().c_str());
200 return true;
201 }
202
Write(const std::string & path,const json & jsonCfg)203 bool ImeCfgManager::Write(const std::string &path, const json &jsonCfg)
204 {
205 std::string cfg = jsonCfg.dump();
206 if (cfg.empty()) {
207 IMSA_HILOGE("imeCfg is empty");
208 return false;
209 }
210 IMSA_HILOGD("imeCfg json: %{public}s", cfg.c_str());
211 auto fd = open(path.c_str(), O_CREAT | O_WRONLY | O_SYNC | O_TRUNC, S_IRUSR | S_IWUSR);
212 if (fd <= 0) {
213 IMSA_HILOGE("file open failed, fd: %{public}d", fd);
214 return false;
215 }
216 auto ret = write(fd, cfg.c_str(), cfg.size());
217 if (ret <= 0) {
218 IMSA_HILOGE("file write failed, ret: %{public}zd", ret);
219 close(fd);
220 return false;
221 }
222 close(fd);
223 return true;
224 }
225 } // namespace MiscServices
226 } // namespace OHOS