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