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