1 /*
2  * Copyright (C) 2024-2024 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 "accessibility_datashare_helper.h"
17 
18 #ifdef OHOS_BUILD_ENABLE_DATA_SHARE
19 #include "datashare_errno.h"
20 #include "datashare_predicates.h"
21 #include "datashare_result_set.h"
22 #include "datashare_values_bucket.h"
23 #endif
24 #include "hilog_wrapper.h"
25 #include "ipc_skeleton.h"
26 #include "iservice_registry.h"
27 #include "system_ability_definition.h"
28 #include "uri.h"
29 #include "utils.h"
30 
31 namespace OHOS {
32 namespace Accessibility {
33 ffrt::mutex AccessibilityDatashareHelper::observerMutex_;
34 namespace {
35 #ifdef OHOS_BUILD_ENABLE_DATA_SHARE
36     constexpr int32_t INDEX = 0;
37     const std::string SETTING_COLUMN_KEYWORD = "KEYWORD";
38     const std::string SETTING_COLUMN_VALUE = "VALUE";
39 #endif
40     constexpr int32_t DECIMAL_NOTATION = 10;
41     const std::string SETTINGS_DATA_EXT_URI = "datashare_ext";
42     const std::string SETTING_GLOBAL_URI = "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA";
43     const std::string SETTING_SYSTEM_URI = "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_";
44     const std::string SETTING_SECURE_URI =
45         "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE_";
46 }
47 
AccessibilityDatashareHelper(DATASHARE_TYPE type, int32_t accountId)48 AccessibilityDatashareHelper::AccessibilityDatashareHelper(DATASHARE_TYPE type, int32_t accountId)
49     :type_(type), accountId_(accountId)
50 {
51     HILOG_DEBUG();
52 }
53 
~AccessibilityDatashareHelper()54 AccessibilityDatashareHelper::~AccessibilityDatashareHelper()
55 {
56 #ifdef OHOS_BUILD_ENABLE_DATA_SHARE
57     if (dataShareHelper_ != nullptr) {
58         DestoryDatashareHelper(dataShareHelper_);
59         dataShareHelper_ = nullptr;
60     }
61 #endif
62 }
63 
GetStringValue(const std::string& key, const std::string& defaultValue)64 std::string AccessibilityDatashareHelper::GetStringValue(const std::string& key, const std::string& defaultValue)
65 {
66     std::string resultStr = defaultValue;
67 #ifdef OHOS_BUILD_ENABLE_DATA_SHARE
68     std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
69     std::shared_ptr<DataShare::DataShareResultSet> resultSet = nullptr;
70     do {
71         std::vector<std::string> columns = { SETTING_COLUMN_VALUE };
72         DataShare::DataSharePredicates predicates;
73         Uri uri(AssembleUri(key));
74         int32_t count = 0;
75         predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
76         if (dataShareHelper_ == nullptr) {
77             break;
78         }
79         resultSet = dataShareHelper_->Query(uri, predicates, columns);
80         if (resultSet == nullptr) {
81             break;
82         }
83         resultSet->GetRowCount(count);
84         if (count == 0) {
85             RetError ret = PutStringValue(key, defaultValue);
86             if (ret != RET_OK) {
87                 HILOG_WARN("put default key failed key = %{public}s", key.c_str());
88             }
89             break;
90         }
91         resultSet->GoToRow(INDEX);
92         int32_t rtn = resultSet->GetString(INDEX, resultStr);
93         if (rtn  != DataShare::E_OK) {
94             break;
95         }
96     } while (0);
97     if (resultSet != nullptr) {
98         resultSet->Close();
99         resultSet = nullptr;
100     }
101     IPCSkeleton::SetCallingIdentity(callingIdentity);
102 #endif
103     return resultStr;
104 }
105 
GetLongValue(const std::string& key, const int64_t& defaultValue)106 int64_t AccessibilityDatashareHelper::GetLongValue(const std::string& key, const int64_t& defaultValue)
107 {
108     int64_t result = defaultValue;
109     std::string valueStr = GetStringValue(key, std::to_string(result));
110     if (valueStr != "") {
111         result = static_cast<int64_t>(std::strtoll(valueStr.c_str(), nullptr, DECIMAL_NOTATION));
112     }
113     return result;
114 }
115 
GetIntValue(const std::string& key, const int32_t& defaultValue)116 int32_t AccessibilityDatashareHelper::GetIntValue(const std::string& key, const int32_t& defaultValue)
117 {
118     int64_t valueLong = GetLongValue(key, defaultValue);
119     return static_cast<int32_t>(valueLong);
120 }
121 
GetBoolValue(const std::string& key, const bool& defaultValue)122 bool AccessibilityDatashareHelper::GetBoolValue(const std::string& key, const bool& defaultValue)
123 {
124     bool result = defaultValue;
125     std::string valueStr = GetStringValue(key, result ? "1" : "0");
126     if (valueStr != "") {
127         result = (valueStr == "1" || valueStr == "true");
128     }
129     return result;
130 }
131 
GetFloatValue(const std::string& key, const float& defaultValue)132 float AccessibilityDatashareHelper::GetFloatValue(const std::string& key, const float& defaultValue)
133 {
134     float result = defaultValue;
135     std::string valueStr = GetStringValue(key, std::to_string(result));
136     if (valueStr != "") {
137         result = std::stof(valueStr);
138     }
139     return result;
140 }
141 
PutStringValue(const std::string& key, const std::string& value, bool needNotify)142 RetError AccessibilityDatashareHelper::PutStringValue(const std::string& key, const std::string& value, bool needNotify)
143 {
144     std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
145     RetError rtn = RET_OK;
146 #ifdef OHOS_BUILD_ENABLE_DATA_SHARE
147     do {
148         if (dataShareHelper_ == nullptr) {
149             rtn = RET_ERR_NULLPTR;
150             break;
151         }
152         DataShare::DataShareValueObject keyObj(key);
153         DataShare::DataShareValueObject valueObj(value);
154         DataShare::DataShareValuesBucket bucket;
155         bucket.Put(SETTING_COLUMN_KEYWORD, keyObj);
156         bucket.Put(SETTING_COLUMN_VALUE, valueObj);
157         DataShare::DataSharePredicates predicates;
158         predicates.EqualTo(SETTING_COLUMN_KEYWORD, key);
159         Uri uri(AssembleUri(key));
160         if (dataShareHelper_->Update(uri, predicates, bucket) <= 0) {
161             HILOG_DEBUG("no data exist, insert one row");
162             auto ret = dataShareHelper_->Insert(uri, bucket);
163             HILOG_INFO("helper insert %{public}s ret(%{public}d).", key.c_str(), static_cast<int>(ret));
164         }
165         if (needNotify) {
166             dataShareHelper_->NotifyChange(AssembleUri(key));
167         }
168     } while (0);
169     IPCSkeleton::SetCallingIdentity(callingIdentity);
170 #endif
171     return rtn;
172 }
173 
PutIntValue(const std::string& key, int32_t value, bool needNotify)174 RetError AccessibilityDatashareHelper::PutIntValue(const std::string& key, int32_t value, bool needNotify)
175 {
176     return PutStringValue(key, std::to_string(value), needNotify);
177 }
178 
PutLongValue(const std::string& key, int64_t value, bool needNotify)179 RetError AccessibilityDatashareHelper::PutLongValue(const std::string& key, int64_t value, bool needNotify)
180 {
181     return PutStringValue(key, std::to_string(value), needNotify);
182 }
183 
PutBoolValue(const std::string& key, bool value, bool needNotify)184 RetError AccessibilityDatashareHelper::PutBoolValue(const std::string& key, bool value, bool needNotify)
185 {
186     std::string valueStr = value ? "1" : "0";
187     return PutStringValue(key, valueStr, needNotify);
188 }
189 
PutFloatValue(const std::string& key, float value, bool needNotify)190 RetError AccessibilityDatashareHelper::PutFloatValue(const std::string& key, float value, bool needNotify)
191 {
192     return PutStringValue(key, std::to_string(value), needNotify);
193 }
194 
Initialize(int32_t systemAbilityId)195 void AccessibilityDatashareHelper::Initialize(int32_t systemAbilityId)
196 {
197     auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
198     if (systemAbilityManager == nullptr) {
199         HILOG_ERROR("get sam return nullptr");
200         return;
201     }
202     auto remoteObj = systemAbilityManager->GetSystemAbility(systemAbilityId);
203     if (remoteObj == nullptr) {
204         HILOG_ERROR("Get remoteObj return nullptr, systemAbilityId=%{public}d", systemAbilityId);
205         return;
206     }
207     remoteObj_ = remoteObj;
208     switch (type_) {
209         case DATASHARE_TYPE::GLOBAL:
210             uriProxyStr_ = SETTING_GLOBAL_URI + "?Proxy=true";
211             break;
212         case DATASHARE_TYPE::SYSTEM:
213             uriProxyStr_ = SETTING_SYSTEM_URI + std::to_string(accountId_) + "?Proxy=true";
214             break;
215         case DATASHARE_TYPE::SECURE:
216             uriProxyStr_ = SETTING_SECURE_URI + std::to_string(accountId_) + "?Proxy=true";
217             break;
218         default:
219             uriProxyStr_ = SETTING_GLOBAL_URI + "?Proxy=true";
220             HILOG_WARN("undefined DATASHARE_TYPE, use global table");
221             break;
222     }
223 #ifdef OHOS_BUILD_ENABLE_DATA_SHARE
224     dataShareHelper_ = CreateDatashareHelper();
225     if (dataShareHelper_ == nullptr) {
226         HILOG_ERROR("create dataShareHelper_ failed");
227     }
228 #endif
229 }
230 
CreateObserver(const std::string& key, AccessibilitySettingObserver::UpdateFunc& func)231 sptr<AccessibilitySettingObserver> AccessibilityDatashareHelper::CreateObserver(const std::string& key,
232     AccessibilitySettingObserver::UpdateFunc& func)
233 {
234     sptr<AccessibilitySettingObserver> observer = new AccessibilitySettingObserver();
235     observer->SetKey(key);
236     observer->SetUpdateFunc(func);
237     return observer;
238 }
239 
RegisterObserver(const sptr<AccessibilitySettingObserver>& observer)240 RetError AccessibilityDatashareHelper::RegisterObserver(const sptr<AccessibilitySettingObserver>& observer)
241 {
242     std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
243     auto uri = AssembleUri(observer->GetKey());
244 #ifdef OHOS_BUILD_ENABLE_DATA_SHARE
245     if (dataShareHelper_ == nullptr) {
246         IPCSkeleton::SetCallingIdentity(callingIdentity);
247         return RET_ERR_NULLPTR;
248     }
249     dataShareHelper_->RegisterObserver(uri, observer);
250 #endif
251     IPCSkeleton::SetCallingIdentity(callingIdentity);
252     HILOG_DEBUG("succeed to register observer of uri=%{public}s", uri.ToString().c_str());
253     return RET_OK;
254 }
255 
RegisterObserver(const std::string& key, AccessibilitySettingObserver::UpdateFunc& func)256 RetError AccessibilityDatashareHelper::RegisterObserver(const std::string& key,
257     AccessibilitySettingObserver::UpdateFunc& func)
258 {
259     sptr<AccessibilitySettingObserver> observer = CreateObserver(key, func);
260     if (observer == nullptr) {
261         return RET_ERR_NULLPTR;
262     }
263     auto iter = settingObserverMap_.find(key);
264     if (iter != settingObserverMap_.end() && iter->second != nullptr) {
265         HILOG_INFO("observer of key = %{public}s already exist", key.c_str());
266         return RET_OK;
267     }
268     if (RegisterObserver(observer) != ERR_OK) {
269         return RET_ERR_NULLPTR;
270     }
271     std::lock_guard<ffrt::mutex> lock(observerMutex_);
272     settingObserverMap_.insert(std::make_pair(key, observer));
273     return RET_OK;
274 }
275 
UnregisterObserver(const sptr<AccessibilitySettingObserver>& observer)276 RetError AccessibilityDatashareHelper::UnregisterObserver(const sptr<AccessibilitySettingObserver>& observer)
277 {
278     std::string callingIdentity = IPCSkeleton::ResetCallingIdentity();
279     auto uri = AssembleUri(observer->GetKey());
280 #ifdef OHOS_BUILD_ENABLE_DATA_SHARE
281     if (dataShareHelper_ == nullptr) {
282         IPCSkeleton::SetCallingIdentity(callingIdentity);
283         return RET_ERR_NULLPTR;
284     }
285     dataShareHelper_->UnregisterObserver(uri, observer);
286 #endif
287     IPCSkeleton::SetCallingIdentity(callingIdentity);
288     HILOG_DEBUG("succeed to unregister observer of uri=%{public}s", uri.ToString().c_str());
289     return RET_OK;
290 }
291 
UnregisterObserver(const std::string& key)292 RetError AccessibilityDatashareHelper::UnregisterObserver(const std::string& key)
293 {
294     std::lock_guard<ffrt::mutex> lock(observerMutex_);
295     auto iter = settingObserverMap_.find(key);
296     if (iter != settingObserverMap_.end() && iter->second != nullptr) {
297         sptr<AccessibilitySettingObserver> observer = iter->second;
298         if (UnregisterObserver(observer) == ERR_OK) {
299             settingObserverMap_.erase(iter);
300             HILOG_DEBUG("succeed to unregister observer of key %{public}s", key.c_str());
301             return RET_OK;
302         } else {
303             settingObserverMap_.erase(iter);
304             HILOG_WARN("failed to unregister observer of key %{public}s", key.c_str());
305             return RET_ERR_FAILED;
306         }
307     }
308     HILOG_WARN("failed to find the key %{public}s", key.c_str());
309     return RET_ERR_FAILED;
310 }
311 
312 #ifdef OHOS_BUILD_ENABLE_DATA_SHARE
CreateDatashareHelper()313 std::shared_ptr<DataShare::DataShareHelper> AccessibilityDatashareHelper::CreateDatashareHelper()
314 {
315     if (remoteObj_ == nullptr) {
316         return nullptr;
317     }
318     std::pair<int, std::shared_ptr<DataShare::DataShareHelper>> ret = DataShare::DataShareHelper::Create(remoteObj_,
319         uriProxyStr_, SETTINGS_DATA_EXT_URI);
320     HILOG_INFO("create helper ret = %{public}d, uri=%{public}s", ret.first, uriProxyStr_.c_str());
321     if (ret.second == nullptr) {
322         Utils::RecordUnavailableEvent(A11yUnavailableEvent::READ_EVENT, A11yError::ERROR_READ_FAILED);
323         return nullptr;
324     }
325     return ret.second;
326 }
327 
DestoryDatashareHelper(std::shared_ptr<DataShare::DataShareHelper>& helper)328 bool AccessibilityDatashareHelper::DestoryDatashareHelper(std::shared_ptr<DataShare::DataShareHelper>& helper)
329 {
330     if (helper && !helper->Release()) {
331         HILOG_WARN("release helper fail.");
332         return false;
333     }
334     return true;
335 }
336 #endif
337 
AssembleUri(const std::string& key)338 Uri AccessibilityDatashareHelper::AssembleUri(const std::string& key)
339 {
340     Uri uri(uriProxyStr_ + "&key=" + key);
341     return uri;
342 }
343 
344 } // namespace Accessibility
345 } // namespace OHOS
346 
347