• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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