1 /*
2 * Copyright (c) 2022 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 #define LOG_TAG "DataShareHelper"
16
17 #include "datashare_helper.h"
18 #include "datashare_helper_impl.h"
19
20 #include "adaptor.h"
21 #include "concurrent_map.h"
22 #include "data_ability_observer_interface.h"
23 #include "data_ability_observer_stub.h"
24 #include "dataobs_mgr_client.h"
25 #include "datashare_errno.h"
26 #include "datashare_log.h"
27 #include "datashare_string_utils.h"
28
29 namespace OHOS {
30 namespace DataShare {
31 using namespace AppExecFwk;
32 namespace {
33 static constexpr const char *DATA_SHARE_PREFIX = "datashare:///";
34 static constexpr const char *FILE_PREFIX = "file://";
35 } // namespace
36 class ObserverImpl : public AAFwk::DataAbilityObserverStub {
37 public:
ObserverImpl(const std::shared_ptr<DataShareObserver> dataShareObserver)38 explicit ObserverImpl(const std::shared_ptr<DataShareObserver> dataShareObserver)
39 : dataShareObserver_(dataShareObserver){};
40 void OnChange();
41 void OnChangeExt(const AAFwk::ChangeInfo &info);
42 static DataShareObserver::ChangeInfo ConvertInfo(const AAFwk::ChangeInfo &info);
43 static AAFwk::ChangeInfo ConvertInfo(const DataShareObserver::ChangeInfo &info);
44 static sptr<ObserverImpl> GetObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer);
45 static bool FindObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer);
46 static bool DeleteObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer);
47 private:
48 struct ObserverParam {
49 sptr<ObserverImpl> obs_;
50 std::list<Uri> uris_;
51 };
52 std::shared_ptr<DataShareObserver> dataShareObserver_;
53 static ConcurrentMap<DataShareObserver *, ObserverParam> observers_;
54 };
55
56 ConcurrentMap<DataShareObserver *, ObserverImpl::ObserverParam> ObserverImpl::observers_;
57
TransferUriPrefix(const std::string &originPrefix, const std::string &replacedPrefix, const std::string &originUriStr)58 std::string DataShareHelper::TransferUriPrefix(const std::string &originPrefix, const std::string &replacedPrefix,
59 const std::string &originUriStr)
60 {
61 if (originUriStr.find(originPrefix) != 0) {
62 return originUriStr;
63 }
64 return replacedPrefix + originUriStr.substr(originPrefix.length());
65 }
66
67 /**
68 * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship
69 * between the ability using the Data template (data share for short) and the associated client process in
70 * a DataShareHelper instance.
71 *
72 * @param token Indicates the System token.
73 * @param strUri Indicates the database table or disk file to operate.
74 *
75 * @return Returns the created DataShareHelper instance.
76 */
Creator( const sptr<IRemoteObject> &token, const std::string &strUri, const std::string &extUri, const int waitTime)77 std::shared_ptr<DataShareHelper> DataShareHelper::Creator(
78 const sptr<IRemoteObject> &token, const std::string &strUri, const std::string &extUri, const int waitTime)
79 {
80 DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__));
81 if (token == nullptr) {
82 LOG_ERROR("token == nullptr");
83 return nullptr;
84 }
85
86 std::string replacedUriStr = TransferUriPrefix(FILE_PREFIX, DATA_SHARE_PREFIX, strUri);
87 Uri uri(replacedUriStr);
88 std::shared_ptr<DataShareHelper> helper = nullptr;
89 if (uri.GetQuery().find("Proxy=true") != std::string::npos) {
90 auto result = CreateServiceHelper(extUri, "");
91 if (result != nullptr && GetSilentProxyStatus(strUri) == E_OK) {
92 return result;
93 }
94 if (extUri.empty()) {
95 return nullptr;
96 }
97 Uri ext(extUri);
98 helper = CreateExtHelper(ext, token, waitTime);
99 } else {
100 helper = CreateExtHelper(uri, token, waitTime);
101 }
102 return helper;
103 }
104
Creator(const string &strUri, const CreateOptions &options, const std::string &bundleName, const int waitTime)105 std::shared_ptr<DataShareHelper> DataShareHelper::Creator(const string &strUri, const CreateOptions &options,
106 const std::string &bundleName, const int waitTime)
107 {
108 DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__));
109 Uri uri(strUri);
110 if (!options.isProxy_ && options.token_ == nullptr) {
111 LOG_ERROR("token is nullptr");
112 return nullptr;
113 }
114 return options.isProxy_ ? CreateServiceHelper("", bundleName) : CreateExtHelper(uri, options.token_, waitTime);
115 }
116
Create(const sptr<IRemoteObject> &token, const std::string &strUri, const std::string &extUri, const int waitTime)117 std::pair<int, std::shared_ptr<DataShareHelper>> DataShareHelper::Create(const sptr<IRemoteObject> &token,
118 const std::string &strUri, const std::string &extUri, const int waitTime)
119 {
120 DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__));
121 if (token == nullptr) {
122 LOG_ERROR("Create helper failed, err: %{public}d", E_TOKEN_EMPTY);
123 return std::make_pair(E_TOKEN_EMPTY, nullptr);
124 }
125 Uri uri(strUri);
126 if (IsProxy(uri)) {
127 auto [ret, helper] = CreateProxyHelper(strUri, extUri);
128 if (helper != nullptr) {
129 return std::make_pair(E_OK, helper);
130 }
131 if (ret == E_BMS_NOT_READY) {
132 LOG_ERROR("BMS not ready, uri:%{publish}s", DataShareStringUtils::Change(strUri).c_str());
133 return std::make_pair(E_DATA_SHARE_NOT_READY, nullptr);
134 }
135 if (ret == E_BUNDLE_NAME_NOT_EXIST) {
136 LOG_ERROR("BundleName not exist, uri:%{publish}s", DataShareStringUtils::Change(strUri).c_str());
137 return std::make_pair(E_BUNDLE_NAME_NOT_EXIST, nullptr);
138 }
139 if (extUri.empty()) {
140 LOG_ERROR("Ext uri empty, err: %{public}d", E_EXT_URI_INVALID);
141 return std::make_pair(E_EXT_URI_INVALID, nullptr);
142 }
143 uri = Uri(extUri);
144 }
145 auto helper = CreateExtHelper(uri, token, waitTime);
146 if (helper != nullptr) {
147 return std::make_pair(E_OK, helper);
148 }
149 return std::make_pair(E_ERROR, nullptr);
150 }
151
CreateServiceHelper(const std::string &extUri, const std::string &bundleName)152 std::shared_ptr<DataShareHelper> DataShareHelper::CreateServiceHelper(const std::string &extUri,
153 const std::string &bundleName)
154 {
155 auto manager = DataShareManagerImpl::GetInstance();
156 if (manager == nullptr) {
157 LOG_ERROR("Manager is nullptr");
158 return nullptr;
159 }
160 manager->SetBundleName(bundleName);
161 if (DataShareManagerImpl::GetServiceProxy() == nullptr) {
162 LOG_ERROR("Service proxy is nullptr.");
163 return nullptr;
164 }
165 return std::make_shared<DataShareHelperImpl>(extUri);
166 }
167
GetSilentProxyStatus(const std::string &uri)168 int DataShareHelper::GetSilentProxyStatus(const std::string &uri)
169 {
170 auto proxy = DataShareManagerImpl::GetServiceProxy();
171 if (proxy == nullptr) {
172 LOG_ERROR("Service proxy is nullptr.");
173 return E_ERROR;
174 }
175 return proxy->GetSilentProxyStatus(uri);
176 }
177
CreateExtHelper(Uri &uri, const sptr<IRemoteObject> &token, const int waitTime)178 std::shared_ptr<DataShareHelper> DataShareHelper::CreateExtHelper(Uri &uri, const sptr<IRemoteObject> &token,
179 const int waitTime)
180 {
181 sptr<DataShareConnection> connection = new (std::nothrow) DataShareConnection(uri, token, waitTime);
182 if (connection == nullptr) {
183 LOG_ERROR("Create DataShareConnection failed.");
184 return nullptr;
185 }
186 auto dataShareConnection =
187 std::shared_ptr<DataShareConnection>(connection.GetRefPtr(), [holder = connection](const auto *) {
188 holder->SetConnectInvalid();
189 holder->DisconnectDataShareExtAbility();
190 });
191 auto manager = DataShareManagerImpl::GetInstance();
192 if (manager == nullptr) {
193 LOG_ERROR("Manager is nullptr");
194 return nullptr;
195 }
196 manager->SetCallCount(__FUNCTION__, uri.ToString());
197 if (dataShareConnection->GetDataShareProxy(uri, token) == nullptr) {
198 LOG_ERROR("connect failed");
199 return nullptr;
200 }
201 return std::make_shared<DataShareHelperImpl>(uri, token, dataShareConnection);
202 }
203
204 /**
205 * Registers an observer to DataObsMgr specified by the given Uri.
206 *
207 * @param uri, Indicates the path of the data to operate.
208 * @param dataObserver, Indicates the DataShareObserver object.
209 * @param isDescendants, Indicates the Whether to note the change of descendants.
210 */
RegisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver, bool isDescendants)211 void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver,
212 bool isDescendants)
213 {
214 if (dataObserver == nullptr) {
215 LOG_ERROR("dataObserver is nullptr");
216 return;
217 }
218 auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
219 if (obsMgrClient == nullptr) {
220 LOG_ERROR("get DataObsMgrClient failed");
221 return;
222 }
223 sptr<ObserverImpl> obs = ObserverImpl::GetObserver(uri, dataObserver);
224 if (obs == nullptr) {
225 LOG_ERROR("new ObserverImpl failed");
226 return;
227 }
228 ErrCode ret = obsMgrClient->RegisterObserverExt(uri, obs, isDescendants);
229 if (ret != ERR_OK) {
230 ObserverImpl::DeleteObserver(uri, dataObserver);
231 }
232 LOG_INFO("Register observerExt, ret:%{public}d, uri:%{public}s",
233 ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str());
234 }
235
236 /**
237 * Deregisters an observer used for DataObsMgr specified by the given Uri.
238 *
239 * @param uri, Indicates the path of the data to operate.
240 * @param dataObserver, Indicates the DataShareObserver object.
241 */
UnregisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver)242 void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver)
243 {
244 if (dataObserver == nullptr) {
245 LOG_ERROR("dataObserver is nullptr");
246 return;
247 }
248 auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
249 if (obsMgrClient == nullptr) {
250 LOG_ERROR("get DataObsMgrClient failed");
251 return;
252 }
253
254 if (!ObserverImpl::FindObserver(uri, dataObserver)) {
255 LOG_ERROR("observer not exit!");
256 return;
257 }
258
259 sptr<ObserverImpl> obs = ObserverImpl::GetObserver(uri, dataObserver);
260 if (obs == nullptr) {
261 LOG_ERROR("new ObserverImpl failed");
262 return;
263 }
264 ErrCode ret = obsMgrClient->UnregisterObserverExt(uri, obs);
265 LOG_INFO("Unregister observerExt, ret:%{public}d, uri:%{public}s",
266 ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str());
267 if (ret != ERR_OK) {
268 return;
269 }
270 ObserverImpl::DeleteObserver(uri, dataObserver);
271 }
272
273 /**
274 * Notifies the registered observers of a change to the data resource specified by Uris.
275 *
276 * @param changeInfo Indicates the info of the data to operate.
277 */
NotifyChangeExt(const DataShareObserver::ChangeInfo &changeInfo)278 void DataShareHelper::NotifyChangeExt(const DataShareObserver::ChangeInfo &changeInfo)
279 {
280 auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
281 if (obsMgrClient == nullptr) {
282 LOG_ERROR("get DataObsMgrClient failed");
283 return;
284 }
285
286 ErrCode ret = obsMgrClient->NotifyChangeExt(ObserverImpl::ConvertInfo(changeInfo));
287 LOG_INFO("Notify changeExt, ret:%{public}d", ret);
288 }
289
OnChange()290 void ObserverImpl::OnChange() {}
291
OnChangeExt(const AAFwk::ChangeInfo &info)292 void ObserverImpl::OnChangeExt(const AAFwk::ChangeInfo &info)
293 {
294 dataShareObserver_->OnChange(ConvertInfo(info));
295 }
296
ConvertInfo(const AAFwk::ChangeInfo &info)297 DataShareObserver::ChangeInfo ObserverImpl::ConvertInfo(const AAFwk::ChangeInfo &info)
298 {
299 DataShareObserver::ChangeInfo changeInfo;
300 changeInfo.changeType_ = static_cast<const DataShareObserver::ChangeType>(info.changeType_);
301 changeInfo.uris_ = std::move(info.uris_);
302 changeInfo.data_ = info.data_;
303 changeInfo.size_ = info.size_;
304 changeInfo.valueBuckets_ = std::move(info.valueBuckets_);
305 return changeInfo;
306 }
307
ConvertInfo(const DataShareObserver::ChangeInfo &info)308 AAFwk::ChangeInfo ObserverImpl::ConvertInfo(const DataShareObserver::ChangeInfo &info)
309 {
310 AAFwk::ChangeInfo changeInfo;
311 changeInfo.changeType_ = static_cast<const AAFwk::ChangeInfo::ChangeType>(info.changeType_);
312 changeInfo.uris_ = std::move(info.uris_);
313 changeInfo.data_ = const_cast<void*>(info.data_);
314 changeInfo.size_ = info.size_;
315 changeInfo.valueBuckets_ =std::move(info.valueBuckets_);
316 return changeInfo;
317 }
318
GetObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)319 sptr<ObserverImpl> ObserverImpl::GetObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
320 {
321 sptr<ObserverImpl> result = nullptr;
322 observers_.Compute(observer.get(), [&result, &uri, &observer](const auto &key, auto &value) {
323 if (value.obs_ == nullptr) {
324 value.obs_ = new (std::nothrow) ObserverImpl(observer);
325 value.uris_.push_back(uri);
326 } else {
327 auto it = std::find(value.uris_.begin(), value.uris_.end(), uri);
328 if (it == value.uris_.end()) {
329 value.uris_.push_back(uri);
330 }
331 }
332
333 result = value.obs_;
334 return result != nullptr;
335 });
336
337 return result;
338 }
339
FindObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)340 bool ObserverImpl::FindObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
341 {
342 auto result = observers_.Find(observer.get());
343 if (result.first) {
344 auto it = std::find(result.second.uris_.begin(), result.second.uris_.end(), uri);
345 if (it == result.second.uris_.end()) {
346 return false;
347 }
348 }
349 return result.first;
350 }
351
DeleteObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)352 bool ObserverImpl::DeleteObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
353 {
354 return observers_.ComputeIfPresent(observer.get(), [&uri](auto &key, auto &value) {
355 value.uris_.remove_if([&uri](const auto &value) {
356 return uri == value;
357 });
358 return !value.uris_.empty();
359 });
360 }
361
SetSilentSwitch(Uri &uri, bool enable)362 int DataShareHelper::SetSilentSwitch(Uri &uri, bool enable)
363 {
364 auto proxy = DataShareManagerImpl::GetServiceProxy();
365 if (proxy == nullptr) {
366 LOG_ERROR("proxy is nullptr");
367 return DATA_SHARE_ERROR;
368 }
369 return proxy->SetSilentSwitch(uri, enable);
370 }
371
IsProxy(Uri &uri)372 bool DataShareHelper::IsProxy(Uri &uri)
373 {
374 return (uri.GetQuery().find("Proxy=true") != std::string::npos || uri.GetScheme() == "datashareproxy");
375 }
376
CreateProxyHelper(const std::string &strUri, const std::string &extUri)377 std::pair<int, std::shared_ptr<DataShareHelper>> DataShareHelper::CreateProxyHelper(const std::string &strUri,
378 const std::string &extUri)
379 {
380 int ret = GetSilentProxyStatus(strUri);
381 auto helper = ret == E_OK ? CreateServiceHelper(extUri) : nullptr;
382 return std::make_pair(ret, helper);
383 }
384
InsertEx(Uri &uri, const DataShareValuesBucket &value)385 std::pair<int32_t, int32_t> DataShareHelper::InsertEx(Uri &uri, const DataShareValuesBucket &value)
386 {
387 return std::make_pair(0, 0);
388 }
389
DeleteEx(Uri &uri, const DataSharePredicates &predicates)390 std::pair<int32_t, int32_t> DataShareHelper::DeleteEx(Uri &uri, const DataSharePredicates &predicates)
391 {
392 return std::make_pair(0, 0);
393 }
394
UpdateEx(Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value)395 std::pair<int32_t, int32_t> DataShareHelper::UpdateEx(Uri &uri, const DataSharePredicates &predicates,
396 const DataShareValuesBucket &value)
397 {
398 return std::make_pair(0, 0);
399 }
400
401 } // namespace DataShare
402 } // namespace OHOS