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 <sys/stat.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21
22 #include <algorithm>
23 #include <cstdio>
24 #include <fstream>
25 #include <string>
26
27 #include "file_ex.h"
28 #include "global.h"
29 #include "parameter.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 const char *DEFAULT_IME_KEY = "persist.sys.default_ime";
36 static constexpr int32_t CONFIG_LEN = 128;
37 static constexpr int32_t SUCCESS = 0;
38 using json = nlohmann::json;
39 } // namespace
GetInstance()40 ImeCfgManager &ImeCfgManager::GetInstance()
41 {
42 static ImeCfgManager instance;
43 return instance;
44 }
45
Init()46 void ImeCfgManager::Init()
47 {
48 std::string path(IME_CFG_DIR);
49 if (CreateCachePath(path, S_IRWXU) != SUCCESS) {
50 IMSA_HILOGE("CreateCachePath failed");
51 return;
52 }
53 ReadImeCfgFile();
54 }
55
ReadImeCfgFile()56 void ImeCfgManager::ReadImeCfgFile()
57 {
58 json jsonConfigs;
59 bool ret = ReadCacheFile(IME_CFG_FILE_PATH, jsonConfigs);
60 if (!ret) {
61 IMSA_HILOGE("ReadJsonFile failed");
62 return;
63 }
64 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
65 FromJson(jsonConfigs, imeConfigs_);
66 }
67
WriteImeCfgFile()68 void ImeCfgManager::WriteImeCfgFile()
69 {
70 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
71 json jsonConfigs;
72 ToJson(jsonConfigs, imeConfigs_);
73 if (!WriteCacheFile(IME_CFG_FILE_PATH, jsonConfigs)) {
74 IMSA_HILOGE("WriteJsonFile failed");
75 }
76 }
77
AddImeCfg(const ImeCfg & cfg)78 void ImeCfgManager::AddImeCfg(const ImeCfg &cfg)
79 {
80 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
81 imeConfigs_.push_back(cfg);
82 WriteImeCfgFile();
83 }
84
ModifyImeCfg(const ImeCfg & cfg)85 void ImeCfgManager::ModifyImeCfg(const ImeCfg &cfg)
86 {
87 std::lock_guard<std::recursive_mutex> lock(imeCfgLock_);
88 for (auto &imeConfig : imeConfigs_) {
89 if (imeConfig.userId == cfg.userId && !cfg.currentIme.empty()) {
90 imeConfig.currentIme = cfg.currentIme;
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 ImeCfg 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 ImeCfg &cfg) { return cfg.userId == userId; });
113 if (it != imeConfigs_.end()) {
114 return *it;
115 }
116 return {};
117 }
118
GetDefaultIme()119 std::string ImeCfgManager::GetDefaultIme()
120 {
121 char value[CONFIG_LEN] = { 0 };
122 auto code = GetParameter(DEFAULT_IME_KEY, "", value, CONFIG_LEN);
123 return code > 0 ? value : "";
124 }
125
FromJson(const json & jsonConfigs,std::vector<ImeCfg> & configs)126 void ImeCfgManager::FromJson(const json &jsonConfigs, std::vector<ImeCfg> &configs)
127 {
128 if (!jsonConfigs.contains("imeCfg_list")) {
129 IMSA_HILOGE("imeCfg_list not find");
130 return;
131 }
132 for (auto &jsonCfg : jsonConfigs["imeCfg_list"]) {
133 ImeCfg cfg;
134 FromJson(jsonCfg, cfg);
135 configs.push_back(cfg);
136 }
137 }
138
ToJson(json & jsonConfigs,const std::vector<ImeCfg> & configs)139 void ImeCfgManager::ToJson(json &jsonConfigs, const std::vector<ImeCfg> &configs)
140 {
141 for (auto &cfg : configs) {
142 json jsonCfg;
143 ToJson(jsonCfg, cfg);
144 jsonConfigs["imeCfg_list"].push_back(jsonCfg);
145 }
146 }
147
CreateCachePath(std::string & path,mode_t pathMode)148 int32_t ImeCfgManager::CreateCachePath(std::string &path, mode_t pathMode)
149 {
150 if (IsCachePathExit(path)) {
151 IMSA_HILOGI("dir: %{public}s exist", path.c_str());
152 return SUCCESS;
153 }
154 return mkdir(path.c_str(), pathMode);
155 }
156
IsCachePathExit(std::string & path)157 bool ImeCfgManager::IsCachePathExit(std::string &path)
158 {
159 return access(path.c_str(), F_OK) == SUCCESS;
160 }
161
ReadCacheFile(const std::string & path,json & jsonCfg)162 bool ImeCfgManager::ReadCacheFile(const std::string &path, json &jsonCfg)
163 {
164 std::ifstream jsonFs(path);
165 if (!jsonFs.is_open()) {
166 IMSA_HILOGE("file read open failed");
167 return false;
168 }
169 jsonCfg = json::parse(jsonFs, nullptr, false);
170 if (jsonCfg.is_null() || jsonCfg.is_discarded()) {
171 IMSA_HILOGE("json parse failed");
172 return false;
173 }
174 IMSA_HILOGI("json: %{public}s", jsonCfg.dump().c_str());
175 return true;
176 }
WriteCacheFile(const std::string & path,const json & jsonCfg)177 bool ImeCfgManager::WriteCacheFile(const std::string &path, const json &jsonCfg)
178 {
179 std::ofstream jsonFs(path);
180 if (!jsonFs.is_open()) {
181 IMSA_HILOGE("file write open failed");
182 return false;
183 }
184 constexpr int32_t width = 2;
185 jsonFs << std::setw(width) << jsonCfg << std::endl;
186 return true;
187 }
188 } // namespace MiscServices
189 } // namespace OHOS