• 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     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