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 if (uri.GetQuery().find("appIndex=") != std::string::npos) {
182 LOG_ERROR("ExtHelper do not support appIndex. Uri:%{public}s",
183 DataShareStringUtils::Anonymous(uri.ToString()).c_str());
184 return nullptr;
185 }
186 sptr<DataShareConnection> connection = new (std::nothrow) DataShareConnection(uri, token, waitTime);
187 if (connection == nullptr) {
188 LOG_ERROR("Create DataShareConnection failed.");
189 return nullptr;
190 }
191 auto dataShareConnection =
192 std::shared_ptr<DataShareConnection>(connection.GetRefPtr(), [holder = connection](const auto *) {
193 holder->SetConnectInvalid();
194 holder->DisconnectDataShareExtAbility();
195 });
196 auto manager = DataShareManagerImpl::GetInstance();
197 if (manager == nullptr) {
198 LOG_ERROR("Manager is nullptr");
199 return nullptr;
200 }
201 manager->SetCallCount(__FUNCTION__, uri.ToString());
202 if (dataShareConnection->GetDataShareProxy(uri, token) == nullptr) {
203 LOG_ERROR("connect failed");
204 return nullptr;
205 }
206 return std::make_shared<DataShareHelperImpl>(uri, token, dataShareConnection);
207 }
208
209 /**
210 * Registers an observer to DataObsMgr specified by the given Uri.
211 *
212 * @param uri, Indicates the path of the data to operate.
213 * @param dataObserver, Indicates the DataShareObserver object.
214 * @param isDescendants, Indicates the Whether to note the change of descendants.
215 */
RegisterObserverExt(const Uri & uri,std::shared_ptr<DataShareObserver> dataObserver,bool isDescendants)216 void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver,
217 bool isDescendants)
218 {
219 if (dataObserver == nullptr) {
220 LOG_ERROR("dataObserver is nullptr");
221 return;
222 }
223 auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
224 if (obsMgrClient == nullptr) {
225 LOG_ERROR("get DataObsMgrClient failed");
226 return;
227 }
228 sptr<ObserverImpl> obs = ObserverImpl::GetObserver(uri, dataObserver);
229 if (obs == nullptr) {
230 LOG_ERROR("new ObserverImpl failed");
231 return;
232 }
233 ErrCode ret = obsMgrClient->RegisterObserverExt(uri, obs, isDescendants);
234 if (ret != ERR_OK) {
235 ObserverImpl::DeleteObserver(uri, dataObserver);
236 }
237 LOG_INFO("Register observerExt, ret:%{public}d, uri:%{public}s",
238 ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str());
239 }
240
241 /**
242 * Deregisters an observer used for DataObsMgr specified by the given Uri.
243 *
244 * @param uri, Indicates the path of the data to operate.
245 * @param dataObserver, Indicates the DataShareObserver object.
246 */
UnregisterObserverExt(const Uri & uri,std::shared_ptr<DataShareObserver> dataObserver)247 void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptr<DataShareObserver> dataObserver)
248 {
249 if (dataObserver == nullptr) {
250 LOG_ERROR("dataObserver is nullptr");
251 return;
252 }
253 auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
254 if (obsMgrClient == nullptr) {
255 LOG_ERROR("get DataObsMgrClient failed");
256 return;
257 }
258
259 if (!ObserverImpl::FindObserver(uri, dataObserver)) {
260 LOG_ERROR("observer not exit!");
261 return;
262 }
263
264 sptr<ObserverImpl> obs = ObserverImpl::GetObserver(uri, dataObserver);
265 if (obs == nullptr) {
266 LOG_ERROR("new ObserverImpl failed");
267 return;
268 }
269 ErrCode ret = obsMgrClient->UnregisterObserverExt(uri, obs);
270 LOG_INFO("Unregister observerExt, ret:%{public}d, uri:%{public}s",
271 ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str());
272 if (ret != ERR_OK) {
273 return;
274 }
275 ObserverImpl::DeleteObserver(uri, dataObserver);
276 }
277
278 /**
279 * Notifies the registered observers of a change to the data resource specified by Uris.
280 *
281 * @param changeInfo Indicates the info of the data to operate.
282 */
NotifyChangeExt(const DataShareObserver::ChangeInfo & changeInfo)283 void DataShareHelper::NotifyChangeExt(const DataShareObserver::ChangeInfo &changeInfo)
284 {
285 auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
286 if (obsMgrClient == nullptr) {
287 LOG_ERROR("get DataObsMgrClient failed");
288 return;
289 }
290
291 ErrCode ret = obsMgrClient->NotifyChangeExt(ObserverImpl::ConvertInfo(changeInfo));
292 LOG_INFO("Notify changeExt, ret:%{public}d", ret);
293 }
294
OnChange()295 void ObserverImpl::OnChange() {}
296
OnChangeExt(const AAFwk::ChangeInfo & info)297 void ObserverImpl::OnChangeExt(const AAFwk::ChangeInfo &info)
298 {
299 dataShareObserver_->OnChange(ConvertInfo(info));
300 }
301
ConvertInfo(const AAFwk::ChangeInfo & info)302 DataShareObserver::ChangeInfo ObserverImpl::ConvertInfo(const AAFwk::ChangeInfo &info)
303 {
304 DataShareObserver::ChangeInfo changeInfo;
305 changeInfo.changeType_ = static_cast<const DataShareObserver::ChangeType>(info.changeType_);
306 changeInfo.uris_ = std::move(info.uris_);
307 changeInfo.data_ = info.data_;
308 changeInfo.size_ = info.size_;
309 changeInfo.valueBuckets_ = std::move(info.valueBuckets_);
310 return changeInfo;
311 }
312
ConvertInfo(const DataShareObserver::ChangeInfo & info)313 AAFwk::ChangeInfo ObserverImpl::ConvertInfo(const DataShareObserver::ChangeInfo &info)
314 {
315 AAFwk::ChangeInfo changeInfo;
316 changeInfo.changeType_ = static_cast<const AAFwk::ChangeInfo::ChangeType>(info.changeType_);
317 changeInfo.uris_ = std::move(info.uris_);
318 changeInfo.data_ = const_cast<void*>(info.data_);
319 changeInfo.size_ = info.size_;
320 changeInfo.valueBuckets_ =std::move(info.valueBuckets_);
321 return changeInfo;
322 }
323
GetObserver(const Uri & uri,const std::shared_ptr<DataShareObserver> & observer)324 sptr<ObserverImpl> ObserverImpl::GetObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
325 {
326 sptr<ObserverImpl> result = nullptr;
327 observers_.Compute(observer.get(), [&result, &uri, &observer](const auto &key, auto &value) {
328 if (value.obs_ == nullptr) {
329 value.obs_ = new (std::nothrow) ObserverImpl(observer);
330 value.uris_.push_back(uri);
331 } else {
332 auto it = std::find(value.uris_.begin(), value.uris_.end(), uri);
333 if (it == value.uris_.end()) {
334 value.uris_.push_back(uri);
335 }
336 }
337
338 result = value.obs_;
339 return result != nullptr;
340 });
341
342 return result;
343 }
344
FindObserver(const Uri & uri,const std::shared_ptr<DataShareObserver> & observer)345 bool ObserverImpl::FindObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
346 {
347 auto result = observers_.Find(observer.get());
348 if (result.first) {
349 auto it = std::find(result.second.uris_.begin(), result.second.uris_.end(), uri);
350 if (it == result.second.uris_.end()) {
351 return false;
352 }
353 }
354 return result.first;
355 }
356
DeleteObserver(const Uri & uri,const std::shared_ptr<DataShareObserver> & observer)357 bool ObserverImpl::DeleteObserver(const Uri& uri, const std::shared_ptr<DataShareObserver> &observer)
358 {
359 return observers_.ComputeIfPresent(observer.get(), [&uri](auto &key, auto &value) {
360 value.uris_.remove_if([&uri](const auto &value) {
361 return uri == value;
362 });
363 return !value.uris_.empty();
364 });
365 }
366
SetSilentSwitch(Uri & uri,bool enable)367 int DataShareHelper::SetSilentSwitch(Uri &uri, bool enable)
368 {
369 auto proxy = DataShareManagerImpl::GetServiceProxy();
370 if (proxy == nullptr) {
371 LOG_ERROR("proxy is nullptr");
372 return DATA_SHARE_ERROR;
373 }
374 return proxy->SetSilentSwitch(uri, enable);
375 }
376
IsProxy(Uri & uri)377 bool DataShareHelper::IsProxy(Uri &uri)
378 {
379 return (uri.GetQuery().find("Proxy=true") != std::string::npos || uri.GetScheme() == "datashareproxy");
380 }
381
CreateProxyHelper(const std::string & strUri,const std::string & extUri)382 std::pair<int, std::shared_ptr<DataShareHelper>> DataShareHelper::CreateProxyHelper(const std::string &strUri,
383 const std::string &extUri)
384 {
385 int ret = GetSilentProxyStatus(strUri);
386 auto helper = ret == E_OK ? CreateServiceHelper(extUri) : nullptr;
387 return std::make_pair(ret, helper);
388 }
389
InsertEx(Uri & uri,const DataShareValuesBucket & value)390 std::pair<int32_t, int32_t> DataShareHelper::InsertEx(Uri &uri, const DataShareValuesBucket &value)
391 {
392 return std::make_pair(0, 0);
393 }
394
DeleteEx(Uri & uri,const DataSharePredicates & predicates)395 std::pair<int32_t, int32_t> DataShareHelper::DeleteEx(Uri &uri, const DataSharePredicates &predicates)
396 {
397 return std::make_pair(0, 0);
398 }
399
UpdateEx(Uri & uri,const DataSharePredicates & predicates,const DataShareValuesBucket & value)400 std::pair<int32_t, int32_t> DataShareHelper::UpdateEx(Uri &uri, const DataSharePredicates &predicates,
401 const DataShareValuesBucket &value)
402 {
403 return std::make_pair(0, 0);
404 }
405
406 } // namespace DataShare
407 } // namespace OHOS