• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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