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
16 #include "setting_provider.h"
17 #include <thread>
18 #include "datashare_predicates.h"
19 #include "datashare_result_set.h"
20 #include "datashare_values_bucket.h"
21 #include "ipc_skeleton.h"
22 #include "iservice_registry.h"
23 #include "window_manager_hilog.h"
24 #include "rdb_errno.h"
25 #include "result_set.h"
26 #include "uri.h"
27 #include "screen_session_manager/include/screen_session_manager.h"
28
29 namespace OHOS {
30 namespace Rosen {
31 SettingProvider* SettingProvider::instance_;
32 std::mutex SettingProvider::mutex_;
33 sptr<IRemoteObject> SettingProvider::remoteObj_;
34 namespace {
35 const std::string SETTING_COLUMN_KEYWORD = "KEYWORD";
36 const std::string SETTING_COLUMN_VALUE = "VALUE";
37 const std::string SETTING_URI_PROXY = "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true";
38 const std::string SETTING_MULTI_USER_URI = "datashare:///com.ohos.settingsdata/entry/settingsdata/";
39 const std::string SETTING_MULTI_USER_TABLE = "USER_SETTINGSDATA_";
40 const std::string SETTING_MULTI_USER_PROXY = "?Proxy=true";
41 constexpr const char *SETTINGS_DATA_EXT_URI = "datashare:///com.ohos.settingsdata.DataAbility";
42 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_DISPLAY, "SettingProvider" };
43 constexpr int32_t PARAM_NUM_TEN = 10;
44 } // namespace
45
~SettingProvider()46 SettingProvider::~SettingProvider()
47 {
48 instance_ = nullptr;
49 remoteObj_ = nullptr;
50 }
51
GetInstance(int32_t systemAbilityId)52 SettingProvider& SettingProvider::GetInstance(int32_t systemAbilityId)
53 {
54 if (instance_ == nullptr) {
55 std::lock_guard<std::mutex> lock(mutex_);
56 if (instance_ == nullptr) {
57 instance_ = new SettingProvider();
58 Initialize(systemAbilityId);
59 }
60 }
61 return *instance_;
62 }
63
GetIntValue(const std::string & key,int32_t & value)64 ErrCode SettingProvider::GetIntValue(const std::string& key, int32_t& value)
65 {
66 int64_t valueLong;
67 ErrCode ret = GetLongValue(key, valueLong);
68 if (ret != ERR_OK) {
69 return ret;
70 }
71 value = static_cast<int32_t>(valueLong);
72 return ERR_OK;
73 }
74
GetLongValue(const std::string & key,int64_t & value)75 ErrCode SettingProvider::GetLongValue(const std::string& key, int64_t& value)
76 {
77 std::string valueStr;
78 ErrCode ret = GetStringValue(key, valueStr);
79 if (ret != ERR_OK) {
80 return ret;
81 }
82 value = static_cast<int64_t>(strtoll(valueStr.c_str(), nullptr, PARAM_NUM_TEN));
83 return ERR_OK;
84 }
85
GetBoolValue(const std::string & key,bool & value)86 ErrCode SettingProvider::GetBoolValue(const std::string& key, bool& value)
87 {
88 std::string valueStr;
89 ErrCode ret = GetStringValue(key, valueStr);
90 if (ret != ERR_OK) {
91 return ret;
92 }
93 value = (valueStr == "true");
94 return ERR_OK;
95 }
96
PutIntValue(const std::string & key,int32_t value,bool needNotify)97 ErrCode SettingProvider::PutIntValue(const std::string& key, int32_t value, bool needNotify)
98 {
99 return PutStringValue(key, std::to_string(value), needNotify);
100 }
101
PutLongValue(const std::string & key,int64_t value,bool needNotify)102 ErrCode SettingProvider::PutLongValue(const std::string& key, int64_t value, bool needNotify)
103 {
104 return PutStringValue(key, std::to_string(value), needNotify);
105 }
106
PutBoolValue(const std::string & key,bool value,bool needNotify)107 ErrCode SettingProvider::PutBoolValue(const std::string& key, bool value, bool needNotify)
108 {
109 std::string valueStr = value ? "true" : "false";
110 return PutStringValue(key, valueStr, needNotify);
111 }
112
IsValidKey(const std::string & key)113 bool SettingProvider::IsValidKey(const std::string& key)
114 {
115 std::string value;
116 ErrCode ret = GetStringValue(key, value);
117 return (ret != ERR_NAME_NOT_FOUND) && (!value.empty());
118 }
119
CreateObserver(const std::string & key,SettingObserver::UpdateFunc & func)120 sptr<SettingObserver> SettingProvider::CreateObserver(const std::string& key, SettingObserver::UpdateFunc& func)
121 {
122 sptr<SettingObserver> observer = new SettingObserver();
123 observer->SetKey(key);
124 observer->SetUpdateFunc(func);
125 return observer;
126 }
127
ExecRegisterCb(const sptr<SettingObserver> & observer)128 void SettingProvider::ExecRegisterCb(const sptr<SettingObserver>& observer)
129 {
130 if (observer == nullptr) {
131 WLOGFE("observer is nullptr");
132 return;
133 }
134 observer->OnChange();
135 }
136
RegisterObserver(const sptr<SettingObserver> & observer)137 ErrCode SettingProvider::RegisterObserver(const sptr<SettingObserver>& observer)
138 {
139 if (observer == nullptr) {
140 return ERR_NO_INIT;
141 }
142 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
143 auto uri = AssembleUri(observer->GetKey());
144 auto helper = CreateDataShareHelper();
145 if (helper == nullptr) {
146 IPCSkeleton::SetCallingIdentity(callingIdentity);
147 return ERR_NO_INIT;
148 }
149 helper->RegisterObserver(uri, observer);
150 helper->NotifyChange(uri);
151 std::thread execCb(SettingProvider::ExecRegisterCb, observer);
152 execCb.detach();
153 ReleaseDataShareHelper(helper);
154 IPCSkeleton::SetCallingIdentity(callingIdentity);
155 WLOGFD("succeed to register observer of uri=%{public}s", uri.ToString().c_str());
156 return ERR_OK;
157 }
158
UnregisterObserver(const sptr<SettingObserver> & observer)159 ErrCode SettingProvider::UnregisterObserver(const sptr<SettingObserver>& observer)
160 {
161 if (observer == nullptr) {
162 return ERR_NO_INIT;
163 }
164 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
165 auto uri = AssembleUri(observer->GetKey());
166 auto helper = CreateDataShareHelper();
167 if (helper == nullptr) {
168 IPCSkeleton::SetCallingIdentity(callingIdentity);
169 return ERR_NO_INIT;
170 }
171 helper->UnregisterObserver(uri, observer);
172 ReleaseDataShareHelper(helper);
173 IPCSkeleton::SetCallingIdentity(callingIdentity);
174 WLOGFD("succeed to unregister observer of uri=%{public}s", uri.ToString().c_str());
175 return ERR_OK;
176 }
177
Initialize(int32_t systemAbilityId)178 void SettingProvider::Initialize(int32_t systemAbilityId)
179 {
180 auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
181 if (sam == nullptr) {
182 WLOGFE("GetSystemAbilityManager return nullptr");
183 return;
184 }
185 auto remoteObj = sam->GetSystemAbility(systemAbilityId);
186 if (remoteObj == nullptr) {
187 WLOGFE("GetSystemAbility return nullptr, systemAbilityId=%{public}d", systemAbilityId);
188 return;
189 }
190 remoteObj_ = remoteObj;
191 }
192
GetStringValue(const std::string & key,std::string & value)193 ErrCode SettingProvider::GetStringValue(const std::string& key, std::string& value)
194 {
195 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
196 auto helper = CreateDataShareHelper();
197 if (helper == nullptr) {
198 IPCSkeleton::SetCallingIdentity(callingIdentity);
199 return ERR_NO_INIT;
200 }
201 std::vector<std::string> columns = {SETTING_COLUMN_VALUE};
202 DataShare::DataSharePredicates predicates;
203 predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
204 Uri uri(AssembleUri(key));
205 auto resultSet = helper->Query(uri, predicates, columns);
206 ReleaseDataShareHelper(helper);
207 if (resultSet == nullptr) {
208 WLOGFE("helper->Query return nullptr");
209 IPCSkeleton::SetCallingIdentity(callingIdentity);
210 return ERR_INVALID_OPERATION;
211 }
212 int32_t count;
213 resultSet->GetRowCount(count);
214 if (count == 0) {
215 WLOGFW("not found value, key=%{public}s, count=%{public}d", key.c_str(), count);
216 IPCSkeleton::SetCallingIdentity(callingIdentity);
217 resultSet->Close();
218 return ERR_NAME_NOT_FOUND;
219 }
220 const int32_t INDEX = 0;
221 resultSet->GoToRow(INDEX);
222 int32_t ret = resultSet->GetString(INDEX, value);
223 if (ret != NativeRdb::E_OK) {
224 WLOGFW("resultSet->GetString return not ok, ret=%{public}d", ret);
225 IPCSkeleton::SetCallingIdentity(callingIdentity);
226 resultSet->Close();
227 return ERR_INVALID_VALUE;
228 }
229 resultSet->Close();
230 IPCSkeleton::SetCallingIdentity(callingIdentity);
231 return ERR_OK;
232 }
233
GetStringValueMultiUser(const std::string & key,std::string & value)234 ErrCode SettingProvider::GetStringValueMultiUser(const std::string& key, std::string& value)
235 {
236 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
237 auto helper = CreateDataShareHelperMultiUser();
238 if (helper == nullptr) {
239 IPCSkeleton::SetCallingIdentity(callingIdentity);
240 return ERR_NO_INIT;
241 }
242 std::vector<std::string> columns = {SETTING_COLUMN_VALUE};
243 DataShare::DataSharePredicates predicates;
244 predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
245 Uri uri(AssembleUriMultiUser(key));
246 auto resultSet = helper->Query(uri, predicates, columns);
247 ReleaseDataShareHelper(helper);
248 if (resultSet == nullptr) {
249 WLOGFE("helper->Query return nullptr");
250 IPCSkeleton::SetCallingIdentity(callingIdentity);
251 return ERR_INVALID_OPERATION;
252 }
253 int32_t count;
254 resultSet->GetRowCount(count);
255 if (count == 0) {
256 WLOGFW("not found value, key=%{public}s, count=%{public}d", key.c_str(), count);
257 IPCSkeleton::SetCallingIdentity(callingIdentity);
258 resultSet->Close();
259 return ERR_NAME_NOT_FOUND;
260 }
261 const int32_t INDEX = 0;
262 resultSet->GoToRow(INDEX);
263 int32_t ret = resultSet->GetString(INDEX, value);
264 if (ret != NativeRdb::E_OK) {
265 WLOGFW("resultSet->GetString return not ok, ret=%{public}d", ret);
266 IPCSkeleton::SetCallingIdentity(callingIdentity);
267 resultSet->Close();
268 return ERR_INVALID_VALUE;
269 }
270 resultSet->Close();
271 IPCSkeleton::SetCallingIdentity(callingIdentity);
272 return ERR_OK;
273 }
274
PutStringValue(const std::string & key,const std::string & value,bool needNotify)275 ErrCode SettingProvider::PutStringValue(const std::string& key, const std::string& value, bool needNotify)
276 {
277 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
278 auto helper = CreateDataShareHelper();
279 if (helper == nullptr) {
280 IPCSkeleton::SetCallingIdentity(callingIdentity);
281 return ERR_NO_INIT;
282 }
283 DataShare::DataShareValueObject keyObj(key);
284 DataShare::DataShareValueObject valueObj(value);
285 DataShare::DataShareValuesBucket bucket;
286 bucket.Put(SETTING_COLUMN_KEYWORD, keyObj);
287 bucket.Put(SETTING_COLUMN_VALUE, valueObj);
288 DataShare::DataSharePredicates predicates;
289 predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
290 Uri uri(AssembleUri(key));
291 if (helper->Update(uri, predicates, bucket) <= 0) {
292 WLOGFD("no data exist, insert one row");
293 helper->Insert(uri, bucket);
294 }
295 if (needNotify) {
296 helper->NotifyChange(AssembleUri(key));
297 }
298 ReleaseDataShareHelper(helper);
299 IPCSkeleton::SetCallingIdentity(callingIdentity);
300 return ERR_OK;
301 }
302
CreateDataShareHelper()303 std::shared_ptr<DataShare::DataShareHelper> SettingProvider::CreateDataShareHelper()
304 {
305 auto helper = DataShare::DataShareHelper::Creator(remoteObj_, SETTING_URI_PROXY, SETTINGS_DATA_EXT_URI);
306 if (helper == nullptr) {
307 WLOGFW("helper is nullptr, uri=%{public}s", SETTING_URI_PROXY.c_str());
308 return nullptr;
309 }
310 return helper;
311 }
312
CreateDataShareHelperMultiUser()313 std::shared_ptr<DataShare::DataShareHelper> SettingProvider::CreateDataShareHelperMultiUser()
314 {
315 std::string uriString = "";
316 int32_t userId = ScreenSessionManager::GetInstance().GetCurrentUserId();
317 if (userId > 0) {
318 WLOGFI("current userId: %{public}d", userId);
319 std::string userIdString = std::to_string(userId);
320 uriString = SETTING_MULTI_USER_URI + SETTING_MULTI_USER_TABLE + userIdString +
321 SETTING_MULTI_USER_PROXY;
322 } else {
323 WLOGFE("invalid userId: %{public}d, use default uri", userId);
324 uriString = SETTING_URI_PROXY;
325 }
326 auto helper = DataShare::DataShareHelper::Creator(remoteObj_, uriString, SETTINGS_DATA_EXT_URI);
327 if (helper == nullptr) {
328 WLOGFW("helper is nullptr, uri=%{public}s", uriString.c_str());
329 return nullptr;
330 }
331 return helper;
332 }
333
ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper> & helper)334 bool SettingProvider::ReleaseDataShareHelper(std::shared_ptr<DataShare::DataShareHelper>& helper)
335 {
336 if (!helper->Release()) {
337 WLOGFW("release helper fail");
338 return false;
339 }
340 return true;
341 }
342
AssembleUri(const std::string & key)343 Uri SettingProvider::AssembleUri(const std::string& key)
344 {
345 Uri uri(SETTING_URI_PROXY + "&key=" + key);
346 return uri;
347 }
348
AssembleUriMultiUser(const std::string & key)349 Uri SettingProvider::AssembleUriMultiUser(const std::string& key)
350 {
351 std::string uriString = "";
352 int32_t userId = ScreenSessionManager::GetInstance().GetCurrentUserId();
353 if (userId > 0) {
354 WLOGFI("current userId: %{public}d", userId);
355 std::string userIdString = std::to_string(userId);
356 uriString = SETTING_MULTI_USER_URI + SETTING_MULTI_USER_TABLE + userIdString +
357 SETTING_MULTI_USER_PROXY + "&key=" + key;
358 } else {
359 WLOGFE("invalid userId: %{public}d, use default uri", userId);
360 uriString = SETTING_URI_PROXY + "&key=" + key;
361 }
362 Uri uri(uriString);
363 return uri;
364 }
365
RegisterObserverByTable(const sptr<SettingObserver> & observer,std::string tableName)366 ErrCode SettingProvider::RegisterObserverByTable(const sptr<SettingObserver>& observer, std::string tableName)
367 {
368 if (observer == nullptr) {
369 return ERR_NO_INIT;
370 }
371 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
372 auto uri = AssembleUriMultiUserByTable(observer->GetKey(), tableName);
373 auto helper = CreateDataShareHelperMultiUserByTable(tableName);
374 if (helper == nullptr) {
375 IPCSkeleton::SetCallingIdentity(callingIdentity);
376 return ERR_NO_INIT;
377 }
378 helper->RegisterObserver(uri, observer);
379 helper->NotifyChange(uri);
380 std::thread execCb(SettingProvider::ExecRegisterCb, observer);
381 execCb.detach();
382 ReleaseDataShareHelper(helper);
383 IPCSkeleton::SetCallingIdentity(callingIdentity);
384 WLOGFD("succeed to register observer of uri=%{public}s", uri.ToString().c_str());
385 return ERR_OK;
386 }
387
UnregisterObserverByTable(const sptr<SettingObserver> & observer,std::string tableName)388 ErrCode SettingProvider::UnregisterObserverByTable(const sptr<SettingObserver>& observer, std::string tableName)
389 {
390 if (observer == nullptr) {
391 return ERR_NO_INIT;
392 }
393 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
394 auto uri = AssembleUriMultiUserByTable(observer->GetKey(), tableName);
395 auto helper = CreateDataShareHelperMultiUserByTable(tableName);
396 if (helper == nullptr) {
397 IPCSkeleton::SetCallingIdentity(callingIdentity);
398 return ERR_NO_INIT;
399 }
400 helper->UnregisterObserver(uri, observer);
401 ReleaseDataShareHelper(helper);
402 IPCSkeleton::SetCallingIdentity(callingIdentity);
403 WLOGFD("succeed to unregister observer of uri=%{public}s", uri.ToString().c_str());
404 return ERR_OK;
405 }
406
GetIntValueMultiUserByTable(const std::string & key,int32_t & value,std::string tableName)407 ErrCode SettingProvider::GetIntValueMultiUserByTable(const std::string& key, int32_t& value, std::string tableName)
408 {
409 int64_t result = 0;
410 ErrCode ret = GetLongValueMultiUserByTable(key, result, tableName);
411 if (ret != ERR_OK) {
412 return ret;
413 }
414 value = static_cast<int32_t>(result);
415 return ERR_OK;
416 }
417
GetLongValueMultiUserByTable(const std::string & key,int64_t & value,std::string tableName)418 ErrCode SettingProvider::GetLongValueMultiUserByTable(const std::string& key, int64_t& value, std::string tableName)
419 {
420 std::string result = "";
421 ErrCode ret = GetStringValueMultiUserByTable(key, result, tableName);
422 if (ret != ERR_OK) {
423 return ret;
424 }
425 value = static_cast<int64_t>(strtoll(result.c_str(), nullptr, PARAM_NUM_TEN));
426 return ERR_OK;
427 }
428
GetStringValueMultiUserByTable(const std::string & key,std::string & value,std::string tableName)429 ErrCode SettingProvider::GetStringValueMultiUserByTable(const std::string& key,
430 std::string& value, std::string tableName)
431 {
432 std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
433 auto helper = CreateDataShareHelperMultiUserByTable(tableName);
434 if (helper == nullptr) {
435 IPCSkeleton::SetCallingIdentity(callingIdentity);
436 return ERR_NO_INIT;
437 }
438 std::vector<std::string> columns = {SETTING_COLUMN_VALUE};
439 DataShare::DataSharePredicates predicates;
440 predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
441 Uri uri(AssembleUriMultiUserByTable(key, tableName));
442 auto resultSet = helper->Query(uri, predicates, columns);
443 ReleaseDataShareHelper(helper);
444 if (resultSet == nullptr) {
445 WLOGFE("helper->Query return nullptr");
446 IPCSkeleton::SetCallingIdentity(callingIdentity);
447 return ERR_INVALID_OPERATION;
448 }
449 int32_t count;
450 resultSet->GetRowCount(count);
451 if (count == 0) {
452 WLOGFW("not found value, key=%{public}s, count=%{public}d", key.c_str(), count);
453 IPCSkeleton::SetCallingIdentity(callingIdentity);
454 resultSet->Close();
455 return ERR_NAME_NOT_FOUND;
456 }
457 const int32_t INDEX = 0;
458 resultSet->GoToRow(INDEX);
459 int32_t ret = resultSet->GetString(INDEX, value);
460 if (ret != NativeRdb::E_OK) {
461 WLOGFW("resultSet->GetString return not ok, ret=%{public}d", ret);
462 IPCSkeleton::SetCallingIdentity(callingIdentity);
463 resultSet->Close();
464 return ERR_INVALID_VALUE;
465 }
466 resultSet->Close();
467 IPCSkeleton::SetCallingIdentity(callingIdentity);
468 return ERR_OK;
469 }
470
CreateDataShareHelperMultiUserByTable(std::string tableName)471 std::shared_ptr<DataShare::DataShareHelper> SettingProvider::CreateDataShareHelperMultiUserByTable(
472 std::string tableName)
473 {
474 std::string address = "";
475 int32_t userId = ScreenSessionManager::GetInstance().GetCurrentUserId();
476 if (userId > 0) {
477 WLOGFD("current userId: %{public}d", userId);
478 std::string userIdString = std::to_string(userId);
479 address = SETTING_MULTI_USER_URI + tableName + userIdString +
480 SETTING_MULTI_USER_PROXY;
481 } else {
482 WLOGFE("invalid userId: %{public}d, use default uri", userId);
483 address = SETTING_URI_PROXY;
484 }
485 auto helper = DataShare::DataShareHelper::Creator(remoteObj_, address, SETTINGS_DATA_EXT_URI);
486 if (helper == nullptr) {
487 WLOGFW("helper is nullptr, uri=%{public}s", address.c_str());
488 return nullptr;
489 }
490 return helper;
491 }
492
AssembleUriMultiUserByTable(const std::string & key,std::string tableName)493 Uri SettingProvider::AssembleUriMultiUserByTable(const std::string& key, std::string tableName)
494 {
495 std::string address = "";
496 int32_t userId = ScreenSessionManager::GetInstance().GetCurrentUserId();
497 if (userId > 0) {
498 WLOGFD("current userId: %{public}d", userId);
499 std::string userIdString = std::to_string(userId);
500 address = SETTING_MULTI_USER_URI + tableName + userIdString +
501 SETTING_MULTI_USER_PROXY + "&key=" + key;
502 } else {
503 WLOGFE("invalid userId: %{public}d, use default uri", userId);
504 address = SETTING_URI_PROXY + "&key=" + key;
505 }
506 Uri uri(address);
507 return uri;
508 }
509 } // namespace Rosen
510 } // namespace OHOS