1 /*
2 * Copyright (c) 2023 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 #include <sstream>
16 #include "settings_data_utils.h"
17
18 #include "ime_info_inquirer.h"
19 #include "iservice_registry.h"
20 #include "system_ability_definition.h"
21
22 namespace OHOS {
23 namespace MiscServices {
24 std::mutex SettingsDataUtils::instanceMutex_;
25 sptr<SettingsDataUtils> SettingsDataUtils::instance_ = nullptr;
~SettingsDataUtils()26 SettingsDataUtils::~SettingsDataUtils()
27 {
28 {
29 std::lock_guard<std::mutex> autoLock(remoteObjMutex_);
30 remoteObj_ = nullptr;
31 }
32 std::lock_guard<decltype(observerListMutex_)> lock(observerListMutex_);
33 if (!observerList_.empty()) {
34 for (auto &iter : observerList_) {
35 UnregisterObserver(iter);
36 }
37 observerList_.clear();
38 }
39 }
40
GetInstance()41 sptr<SettingsDataUtils> SettingsDataUtils::GetInstance()
42 {
43 if (instance_ == nullptr) {
44 std::lock_guard<std::mutex> autoLock(instanceMutex_);
45 if (instance_ == nullptr) {
46 IMSA_HILOGI("GetInstance need new SettingsDataUtils.");
47 instance_ = new (std::nothrow) SettingsDataUtils();
48 if (instance_ == nullptr) {
49 IMSA_HILOGE("instance is nullptr!");
50 return instance_;
51 }
52 }
53 }
54 return instance_;
55 }
56
CreateAndRegisterObserver(const std::string & key,SettingsDataObserver::CallbackFunc func)57 int32_t SettingsDataUtils::CreateAndRegisterObserver(const std::string &key, SettingsDataObserver::CallbackFunc func)
58 {
59 IMSA_HILOGD("key: %{public}s.", key.c_str());
60 sptr<SettingsDataObserver> observer = new (std::nothrow) SettingsDataObserver(key, func);
61 if (observer == nullptr) {
62 IMSA_HILOGE("observer is nullptr!");
63 return ErrorCode::ERROR_NULL_POINTER;
64 }
65 return RegisterObserver(observer);
66 }
67
RegisterObserver(const sptr<SettingsDataObserver> & observer)68 int32_t SettingsDataUtils::RegisterObserver(const sptr<SettingsDataObserver> &observer)
69 {
70 if (observer == nullptr) {
71 IMSA_HILOGE("observer is nullptr!");
72 return ErrorCode::ERROR_NULL_POINTER;
73 }
74
75 auto uri = GenerateTargetUri(std::string(SETTING_URI_PROXY), observer->GetKey());
76 auto helper = SettingsDataUtils::CreateDataShareHelper(std::string(SETTING_URI_PROXY));
77 if (helper == nullptr) {
78 IMSA_HILOGE("helper is nullptr!");
79 return ErrorCode::ERROR_NULL_POINTER;
80 }
81 helper->RegisterObserver(uri, observer);
82 ReleaseDataShareHelper(helper);
83 IMSA_HILOGD("succeed to register observer of uri: %{public}s.", uri.ToString().c_str());
84
85 std::lock_guard<decltype(observerListMutex_)> lock(observerListMutex_);
86 observerList_.push_back(observer);
87 return ErrorCode::NO_ERROR;
88 }
89
UnregisterObserver(const sptr<SettingsDataObserver> & observer)90 int32_t SettingsDataUtils::UnregisterObserver(const sptr<SettingsDataObserver> &observer)
91 {
92 auto uri = GenerateTargetUri(std::string(SETTING_URI_PROXY), observer->GetKey());
93 auto helper = SettingsDataUtils::CreateDataShareHelper(std::string(SETTING_URI_PROXY));
94 if (helper == nullptr) {
95 return ErrorCode::ERROR_ENABLE_IME;
96 }
97 helper->UnregisterObserver(uri, observer);
98 ReleaseDataShareHelper(helper);
99 IMSA_HILOGD("succeed to unregister observer of uri: %{public}s.", uri.ToString().c_str());
100 return ErrorCode::NO_ERROR;
101 }
102
CreateDataShareHelper(const std::string & uriProxy)103 std::shared_ptr<DataShare::DataShareHelper> SettingsDataUtils::CreateDataShareHelper(const std::string &uriProxy)
104 {
105 auto remoteObj = GetToken();
106 if (remoteObj == nullptr) {
107 IMSA_HILOGE("remoteObk is nullptr!");
108 return nullptr;
109 }
110
111 auto helper = DataShare::DataShareHelper::Creator(remoteObj_, uriProxy, std::string(SETTINGS_DATA_EXT_URI));
112 if (helper == nullptr) {
113 IMSA_HILOGE("create helper failed, uri: %{public}s!", uriProxy.c_str());
114 return nullptr;
115 }
116 return helper;
117 }
118
ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper> & helper)119 bool SettingsDataUtils::ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper> &helper)
120 {
121 if (helper == nullptr) {
122 IMSA_HILOGW("helper is nullptr.");
123 return true;
124 }
125 if (!helper->Release()) {
126 IMSA_HILOGE("release data share helper failed.");
127 return false;
128 }
129 return true;
130 }
131
GenerateTargetUri(const std::string & uriProxy,const std::string & key)132 Uri SettingsDataUtils::GenerateTargetUri(const std::string &uriProxy, const std::string &key)
133 {
134 Uri uri(std::string(uriProxy) + "&key=" + key);
135 return uri;
136 }
137
SetStringValue(const std::string & uriProxy,const std::string & key,const std::string & value)138 bool SettingsDataUtils::SetStringValue(const std::string &uriProxy, const std::string &key, const std::string &value)
139 {
140 IMSA_HILOGD("start.");
141 auto helper = CreateDataShareHelper(uriProxy);
142 if (helper == nullptr) {
143 IMSA_HILOGE("helper is nullptr.");
144 return false;
145 }
146 DataShare::DataShareValueObject keyObj(key);
147 DataShare::DataShareValueObject valueObj(value);
148 DataShare::DataShareValuesBucket bucket;
149 bucket.Put(SETTING_COLUMN_KEYWORD, keyObj);
150 bucket.Put(SETTING_COLUMN_VALUE, valueObj);
151 DataShare::DataSharePredicates predicates;
152 predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
153 Uri uri(GenerateTargetUri(uriProxy, key));
154 if (helper->Update(uri, predicates, bucket) <= 0) {
155 int index = helper->Insert(uri, bucket);
156 IMSA_HILOGI("no data exists, insert ret index: %{public}d", index);
157 } else {
158 IMSA_HILOGI("data exits");
159 }
160 bool ret = ReleaseDataShareHelper(helper);
161 IMSA_HILOGI("ReleaseDataShareHelper isSuccess: %{public}d", ret);
162 return ret;
163 }
164
GetStringValue(const std::string & uriProxy,const std::string & key,std::string & value)165 int32_t SettingsDataUtils::GetStringValue(const std::string &uriProxy, const std::string &key, std::string &value)
166 {
167 IMSA_HILOGD("start.");
168 auto helper = CreateDataShareHelper(uriProxy);
169 if (helper == nullptr) {
170 IMSA_HILOGE("helper is nullptr.");
171 return ErrorCode::ERROR_NULL_POINTER;
172 }
173 std::vector<std::string> columns = { SETTING_COLUMN_VALUE };
174 DataShare::DataSharePredicates predicates;
175 predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
176 Uri uri(GenerateTargetUri(uriProxy, key));
177 auto resultSet = helper->Query(uri, predicates, columns);
178 ReleaseDataShareHelper(helper);
179 if (resultSet == nullptr) {
180 IMSA_HILOGE("resultSet is nullptr.");
181 return ErrorCode::ERROR_NULL_POINTER;
182 }
183
184 int32_t count = 0;
185 resultSet->GetRowCount(count);
186 if (count <= 0) {
187 IMSA_HILOGW("not found keyword, key: %{public}s, count: %{public}d.", key.c_str(), count);
188 resultSet->Close();
189 return ErrorCode::ERROR_KEYWORD_NOT_FOUND;
190 }
191
192 int32_t columIndex = 0;
193 resultSet->GoToFirstRow();
194 resultSet->GetColumnIndex(SETTING_COLUMN_VALUE, columIndex);
195 int32_t ret = resultSet->GetString(columIndex, value);
196 if (ret != DataShare::E_OK) {
197 IMSA_HILOGE("failed to GetString, ret: %{public}d!", ret);
198 }
199 resultSet->Close();
200 return ret;
201 }
202
GetToken()203 sptr<IRemoteObject> SettingsDataUtils::GetToken()
204 {
205 std::lock_guard<std::mutex> autoLock(remoteObjMutex_);
206 if (remoteObj_ != nullptr) {
207 return remoteObj_;
208 }
209 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
210 if (samgr == nullptr) {
211 IMSA_HILOGE("system ability manager is nullptr!");
212 return nullptr;
213 }
214 auto remoteObj = samgr->GetSystemAbility(INPUT_METHOD_SYSTEM_ABILITY_ID);
215 if (remoteObj == nullptr) {
216 IMSA_HILOGE("system ability is nullptr!");
217 return nullptr;
218 }
219 remoteObj_ = remoteObj;
220 return remoteObj_;
221 }
222
EnableIme(int32_t userId,const std::string & bundleName)223 bool SettingsDataUtils::EnableIme(int32_t userId, const std::string &bundleName)
224 {
225 const int32_t mainUserId = 100;
226 if (userId != mainUserId) {
227 IMSA_HILOGE("user is not main.");
228 return false;
229 }
230 const char *settingKey = "settings.inputmethod.enable_ime";
231 std::string settingValue = "";
232 GetStringValue(std::string(SETTING_URI_PROXY), settingKey, settingValue);
233 IMSA_HILOGI("settingValue: %{public}s", settingValue.c_str());
234 std::string value = "";
235 if (settingValue == "") {
236 value = "{\"enableImeList\" : {\"100\" : [\"" + bundleName + "\"]}}";
237 } else {
238 value = SetSettingValues(settingValue, bundleName);
239 }
240 IMSA_HILOGI("value: %{public}s", value.c_str());
241 return SetStringValue(std::string(SETTING_URI_PROXY), settingKey, value);
242 }
243
split(const std::string & text,char delim)244 std::vector<std::string> SettingsDataUtils::split(const std::string &text, char delim)
245 {
246 std::vector<std::string> tokens;
247 std::stringstream ss(text);
248 std::string item;
249 while (std::getline(ss, item, delim)) {
250 if (!item.empty()) {
251 tokens.push_back(item);
252 }
253 }
254 return tokens;
255 }
256
SetSettingValues(const std::string & settingValue,const std::string & bundleName)257 std::string SettingsDataUtils::SetSettingValues(const std::string &settingValue, const std::string &bundleName)
258 {
259 std::string value = "";
260 std::vector<std::string> settingValues = split(settingValue, ']');
261 for (uint32_t i = 0; i < settingValues.size(); ++i) {
262 if (i == 0) {
263 if (settingValues[0].back() == '[') {
264 value += settingValues[i] + "\"" + bundleName + "\"" + "]";
265 } else {
266 value += settingValues[i] + ",\"" + bundleName + "\"" + "]";
267 }
268 } else {
269 value += settingValues[i];
270 }
271 }
272 return value;
273 }
274 } // namespace MiscServices
275 } // namespace OHOS