• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "datashare_helper.h"
17 
18 #include "datashare_result_set.h"
19 #include "data_share_manager.h"
20 #include "data_ability_observer_interface.h"
21 #include "dataobs_mgr_client.h"
22 #include "datashare_log.h"
23 #include "idatashare.h"
24 
25 namespace OHOS {
26 namespace DataShare {
27 using namespace AppExecFwk;
28 namespace {
29 const std::string SCHEME_DATASHARE = "datashare";
30 constexpr int INVALID_VALUE = -1;
31 }  // namespace
32 
DataShareHelper(const sptr<IRemoteObject> & token,const Uri & uri,sptr<DataShareConnection> dataShareConnection)33 DataShareHelper::DataShareHelper(const sptr<IRemoteObject> &token, const Uri &uri,
34     sptr<DataShareConnection> dataShareConnection)
35 {
36     LOG_INFO("DataShareHelper::DataShareHelper start");
37     token_ = token;
38     uri_ = uri;
39     dataShareConnection_ = dataShareConnection;
40 }
41 
DataShareHelper(const sptr<IRemoteObject> & token,const Uri & uri)42 DataShareHelper::DataShareHelper(const sptr<IRemoteObject> &token, const Uri &uri)
43 {
44     LOG_INFO("DataShareHelper::DataShareHelper start");
45     token_ = token;
46     uri_ = uri;
47     isDataShareService_ = (uri_.GetQuery().find("Proxy=true") != std::string::npos);
48     LOG_INFO("DataShareHelper::DataShareHelper end");
49 }
50 
~DataShareHelper()51 DataShareHelper::~DataShareHelper()
52 {
53 }
54 
55 /**
56  * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship
57  * between the ability using the Data template (data share for short) and the associated client process in
58  * a DataShareHelper instance.
59  *
60  * @param context Indicates the Context object on OHOS.
61  * @param strUri Indicates the database table or disk file to operate.
62  *
63  * @return Returns the created DataShareHelper instance.
64  */
Creator(const std::shared_ptr<Context> & context,const std::string & strUri)65 std::shared_ptr<DataShareHelper> DataShareHelper::Creator(
66     const std::shared_ptr<Context> &context, const std::string &strUri)
67 {
68     if (context == nullptr) {
69         LOG_ERROR("DataShareHelper::Creator failed, context == nullptr");
70         return nullptr;
71     }
72     sptr<IRemoteObject> token = context->GetToken();
73     return Creator(token, strUri);
74 }
75 
76 /**
77  * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship
78  * between the ability using the Data template (data share for short) and the associated client process in
79  * a DataShareHelper instance.
80  *
81  * @param context Indicates the Context object on OHOS.
82  * @param strUri Indicates the database table or disk file to operate.
83  *
84  * @return Returns the created DataShareHelper instance.
85  */
Creator(const std::shared_ptr<OHOS::AbilityRuntime::Context> & context,const std::string & strUri)86 std::shared_ptr<DataShareHelper> DataShareHelper::Creator(
87     const std::shared_ptr<OHOS::AbilityRuntime::Context> &context, const std::string &strUri)
88 {
89     if (context == nullptr) {
90         LOG_ERROR("DataShareHelper::Creator failed, context == nullptr");
91         return nullptr;
92     }
93     sptr<IRemoteObject> token = context->GetToken();
94     return Creator(token, strUri);
95 }
96 
97 /**
98  * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship
99  * between the ability using the Data template (data share for short) and the associated client process in
100  * a DataShareHelper instance.
101  *
102  * @param token Indicates the System token.
103  * @param strUri Indicates the database table or disk file to operate.
104  *
105  * @return Returns the created DataShareHelper instance.
106  */
Creator(const sptr<IRemoteObject> & token,const std::string & strUri)107 std::shared_ptr<DataShareHelper> DataShareHelper::Creator(const sptr<IRemoteObject> &token, const std::string &strUri)
108 {
109     if (token == nullptr) {
110         LOG_ERROR("token == nullptr");
111         return nullptr;
112     }
113 
114     Uri uri(strUri);
115     if (uri.GetScheme() != SCHEME_DATASHARE) {
116         LOG_ERROR("the Scheme is not datashare, Scheme: %{public}s", uri.GetScheme().c_str());
117         return nullptr;
118     }
119     if ((uri.GetQuery().find("Proxy=true") != std::string::npos) &&
120         DataShareManager::GetDataShareService() != nullptr) {
121         DataShareHelper *dataShareHelper = new (std::nothrow) DataShareHelper(token, uri);
122         if (dataShareHelper) {
123             return std::shared_ptr<DataShareHelper>(dataShareHelper);
124         }
125         LOG_ERROR("create DataShareHelper failed");
126     }
127     sptr<DataShareConnection> dataShareConnection = new (std::nothrow) DataShareConnection(uri);
128     if (dataShareConnection == nullptr) {
129         LOG_ERROR("create dataShareConnection failed");
130         return nullptr;
131     }
132     if (!dataShareConnection->ConnectDataShareExtAbility(uri, token)) {
133         LOG_ERROR("connect failed");
134         return nullptr;
135     }
136 
137     DataShareHelper *ptrDataShareHelper =
138         new (std::nothrow) DataShareHelper(token, uri, dataShareConnection);
139     if (ptrDataShareHelper == nullptr) {
140         LOG_ERROR("create DataShareHelper failed");
141         dataShareConnection = nullptr;
142         return nullptr;
143     }
144 
145     return std::shared_ptr<DataShareHelper>(ptrDataShareHelper);
146 }
147 
148 /**
149  * @brief Releases the client resource of the data share.
150  * You should call this method to releases client resource after the data operations are complete.
151  *
152  * @return Returns true if the resource is successfully released; returns false otherwise.
153  */
Release()154 bool DataShareHelper::Release()
155 {
156     LOG_INFO("Release Start");
157     dataShareConnection_ = nullptr;
158     uri_ = Uri("");
159     return true;
160 }
161 
162 /**
163  * @brief Obtains the MIME types of files supported.
164  *
165  * @param uri Indicates the path of the files to obtain.
166  * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null.
167  *
168  * @return Returns the matched MIME types. If there is no match, null is returned.
169  */
GetFileTypes(Uri & uri,const std::string & mimeTypeFilter)170 std::vector<std::string> DataShareHelper::GetFileTypes(Uri &uri, const std::string &mimeTypeFilter)
171 {
172     std::vector<std::string> matchedMIMEs;
173     auto connection = dataShareConnection_;
174     if (connection == nullptr) {
175         LOG_ERROR("dataShareConnection_ is nullptr");
176         return matchedMIMEs;
177     }
178 
179     if (!connection->ConnectDataShareExtAbility(uri_, token_)) {
180         LOG_ERROR("dataShareProxy is nullptr");
181         return matchedMIMEs;
182     }
183 
184     auto proxy = connection->GetDataShareProxy();
185     if (proxy != nullptr) {
186         matchedMIMEs = proxy->GetFileTypes(uri, mimeTypeFilter);
187     }
188     return matchedMIMEs;
189 }
190 
191 /**
192  * @brief Opens a file in a specified remote path.
193  *
194  * @param uri Indicates the path of the file to open.
195  * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access
196  * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file,
197  * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data,
198  *  or "rwt" for read and write access that truncates any existing file.
199  *
200  * @return Returns the file descriptor.
201  */
OpenFile(Uri & uri,const std::string & mode)202 int DataShareHelper::OpenFile(Uri &uri, const std::string &mode)
203 {
204     int fd = INVALID_VALUE;
205     auto connection = dataShareConnection_;
206     if (connection == nullptr) {
207         LOG_ERROR("dataShareConnection_ is nullptr");
208         return fd;
209     }
210 
211     if (!connection->ConnectDataShareExtAbility(uri_, token_)) {
212         LOG_ERROR("dataShareProxy is nullptr");
213         return fd;
214     }
215 
216     auto proxy = connection->GetDataShareProxy();
217     if (proxy != nullptr) {
218         fd = proxy->OpenFile(uri, mode);
219     }
220     return fd;
221 }
222 
223 /**
224  * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets
225  * inside of their .hap.
226  *
227  * @param uri Indicates the path of the file to open.
228  * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access
229  * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file,
230  * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing
231  * data, or "rwt" for read and write access that truncates any existing file.
232  *
233  * @return Returns the RawFileDescriptor object containing file descriptor.
234  */
OpenRawFile(Uri & uri,const std::string & mode)235 int DataShareHelper::OpenRawFile(Uri &uri, const std::string &mode)
236 {
237     int fd = INVALID_VALUE;
238     auto connection = dataShareConnection_;
239     if (connection == nullptr) {
240         LOG_ERROR("dataShareConnection_ is nullptr");
241         return fd;
242     }
243 
244     if (!connection->ConnectDataShareExtAbility(uri_, token_)) {
245         LOG_ERROR("dataShareProxy is nullptr");
246         return fd;
247     }
248 
249     auto proxy = connection->GetDataShareProxy();
250     if (proxy != nullptr) {
251         fd = proxy->OpenRawFile(uri, mode);
252     }
253     return fd;
254 }
255 
256 /**
257  * @brief Inserts a single data record into the database.
258  *
259  * @param uri Indicates the path of the data to operate.
260  * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted.
261  *
262  * @return Returns the index of the inserted data record.
263  */
Insert(Uri & uri,const DataShareValuesBucket & value)264 int DataShareHelper::Insert(Uri &uri, const DataShareValuesBucket &value)
265 {
266     int index = INVALID_VALUE;
267     if (isDataShareService_) {
268         auto service = DataShareManager::GetDataShareService();
269         if (!service) {
270             return index;
271         }
272         return service->Insert(uri.ToString(), value);
273     }
274     auto connection = dataShareConnection_;
275     if (connection == nullptr) {
276         LOG_ERROR("dataShareConnection_ is nullptr");
277         return index;
278     }
279 
280     if (!connection->ConnectDataShareExtAbility(uri_, token_)) {
281         LOG_ERROR("dataShareProxy is nullptr");
282         return index;
283     }
284 
285     auto proxy = connection->GetDataShareProxy();
286     if (proxy != nullptr) {
287         index = proxy->Insert(uri, value);
288     }
289     return index;
290 }
291 
292 /**
293  * @brief Updates data records in the database.
294  *
295  * @param uri Indicates the path of data to update.
296  * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null.
297  * @param value Indicates the data to update. This parameter can be null.
298  *
299  * @return Returns the number of data records updated.
300  */
Update(Uri & uri,const DataSharePredicates & predicates,const DataShareValuesBucket & value)301 int DataShareHelper::Update(
302     Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value)
303 {
304     int index = INVALID_VALUE;
305     if (isDataShareService_) {
306         auto service = DataShareManager::GetDataShareService();
307         if (!service) {
308             return index;
309         }
310         return service->Update(uri.ToString(), predicates, value);
311     }
312 
313     auto connection = dataShareConnection_;
314     if (connection == nullptr) {
315         LOG_ERROR("dataShareConnection_ is nullptr");
316         return index;
317     }
318 
319     if (!connection->ConnectDataShareExtAbility(uri_, token_)) {
320         LOG_ERROR("dataShareProxy is nullptr");
321         return index;
322     }
323 
324     auto proxy = connection->GetDataShareProxy();
325     if (proxy != nullptr) {
326         index = proxy->Update(uri, predicates, value);
327     }
328     return index;
329 }
330 
331 /**
332  * @brief Deletes one or more data records from the database.
333  *
334  * @param uri Indicates the path of the data to operate.
335  * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null.
336  *
337  * @return Returns the number of data records deleted.
338  */
Delete(Uri & uri,const DataSharePredicates & predicates)339 int DataShareHelper::Delete(Uri &uri, const DataSharePredicates &predicates)
340 {
341     int index = INVALID_VALUE;
342     if (isDataShareService_) {
343         auto service = DataShareManager::GetDataShareService();
344         if (!service) {
345             return index;
346         }
347         return service->Delete(uri.ToString(), predicates);
348     }
349 
350     auto connection = dataShareConnection_;
351     if (connection == nullptr) {
352         LOG_ERROR("dataShareConnection_ is nullptr");
353         return index;
354     }
355 
356     if (!connection->ConnectDataShareExtAbility(uri_, token_)) {
357         LOG_ERROR("dataShareProxy is nullptr");
358         return index;
359     }
360 
361     auto proxy = connection->GetDataShareProxy();
362     if (proxy != nullptr) {
363         index = proxy->Delete(uri, predicates);
364     }
365     return index;
366 }
367 
368 /**
369  * @brief Deletes one or more data records from the database.
370  *
371  * @param uri Indicates the path of data to query.
372  * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null.
373  * @param columns Indicates the columns to query. If this parameter is null, all columns are queried.
374  *
375  * @return Returns the query result.
376  */
Query(Uri & uri,const DataSharePredicates & predicates,std::vector<std::string> & columns)377 std::shared_ptr<DataShareResultSet> DataShareHelper::Query(
378     Uri &uri, const DataSharePredicates &predicates, std::vector<std::string> &columns)
379 {
380     std::shared_ptr<DataShareResultSet> resultset = nullptr;
381     if (isDataShareService_) {
382         auto service = DataShareManager::GetDataShareService();
383         if (!service) {
384             return nullptr;
385         }
386         return service->Query(uri.ToString(), predicates, columns);
387     }
388 
389     auto connection = dataShareConnection_;
390     if (connection == nullptr) {
391         LOG_ERROR("dataShareConnection_ is nullptr");
392         return resultset;
393     }
394 
395     if (!connection->ConnectDataShareExtAbility(uri_, token_)) {
396         LOG_ERROR("dataShareProxy is nullptr");
397         return resultset;
398     }
399 
400     auto proxy = connection->GetDataShareProxy();
401     if (proxy != nullptr) {
402         resultset = proxy->Query(uri, predicates, columns);
403     }
404     return resultset;
405 }
406 
407 /**
408  * @brief Obtains the MIME type matching the data specified by the URI of the data share. This method should be
409  * implemented by a data share. Data abilities supports general data types, including text, HTML, and JPEG.
410  *
411  * @param uri Indicates the URI of the data.
412  *
413  * @return Returns the MIME type that matches the data specified by uri.
414  */
GetType(Uri & uri)415 std::string DataShareHelper::GetType(Uri &uri)
416 {
417     std::string type;
418 
419     auto connection = dataShareConnection_;
420     if (connection == nullptr) {
421         LOG_ERROR("dataShareConnection_ is nullptr");
422         return type;
423     }
424 
425     if (!connection->ConnectDataShareExtAbility(uri_, token_)) {
426         LOG_ERROR("dataShareProxy is nullptr");
427         return type;
428     }
429 
430     auto proxy = connection->GetDataShareProxy();
431     if (proxy != nullptr) {
432         type = proxy->GetType(uri);
433     }
434     return type;
435 }
436 
437 /**
438  * @brief Inserts multiple data records into the database.
439  *
440  * @param uri Indicates the path of the data to operate.
441  * @param values Indicates the data records to insert.
442  *
443  * @return Returns the number of data records inserted.
444  */
BatchInsert(Uri & uri,const std::vector<DataShareValuesBucket> & values)445 int DataShareHelper::BatchInsert(Uri &uri, const std::vector<DataShareValuesBucket> &values)
446 {
447     int ret = INVALID_VALUE;
448     auto connection = dataShareConnection_;
449     if (connection == nullptr) {
450         LOG_ERROR("dataShareConnection_ is nullptr");
451         return ret;
452     }
453 
454     if (!connection->ConnectDataShareExtAbility(uri_, token_)) {
455         LOG_ERROR("dataShareProxy is nullptr");
456         return ret;
457     }
458 
459     auto proxy = connection->GetDataShareProxy();
460     if (proxy != nullptr) {
461         ret = proxy->BatchInsert(uri, values);
462     }
463     return ret;
464 }
465 
466 /**
467  * @brief Registers an observer to DataObsMgr specified by the given Uri.
468  *
469  * @param uri, Indicates the path of the data to operate.
470  * @param dataObserver, Indicates the IDataAbilityObserver object.
471  */
RegisterObserver(const Uri & uri,const sptr<AAFwk::IDataAbilityObserver> & dataObserver)472 void DataShareHelper::RegisterObserver(const Uri &uri, const sptr<AAFwk::IDataAbilityObserver> &dataObserver)
473 {
474     LOG_INFO("Start");
475     if (dataObserver == nullptr) {
476         LOG_ERROR("dataObserver is nullptr");
477         return;
478     }
479     if (isDataShareService_) {
480         if (!RegObserver(uri, dataObserver)) {
481             LOG_ERROR("RegisterObserver failed");
482         }
483         return;
484     }
485 
486     auto connection = dataShareConnection_;
487     if (connection == nullptr) {
488         LOG_ERROR("dataShareConnection_ is nullptr");
489         return;
490     }
491 
492     if (!connection->ConnectDataShareExtAbility(uri, token_)) {
493         LOG_ERROR("connect failed");
494         return;
495     }
496 
497     auto proxy = connection->GetDataShareProxy();
498     if (proxy == nullptr) {
499         LOG_ERROR("proxy has disconnected");
500         return;
501     }
502     proxy->RegisterObserver(uri, dataObserver);
503 }
504 
505 /**
506  * @brief Deregisters an observer used for DataObsMgr specified by the given Uri.
507  *
508  * @param uri, Indicates the path of the data to operate.
509  * @param dataObserver, Indicates the IDataAbilityObserver object.
510  */
UnregisterObserver(const Uri & uri,const sptr<AAFwk::IDataAbilityObserver> & dataObserver)511 void DataShareHelper::UnregisterObserver(const Uri &uri, const sptr<AAFwk::IDataAbilityObserver> &dataObserver)
512 {
513     LOG_INFO("Start");
514     if (dataObserver == nullptr) {
515         LOG_ERROR("dataObserver is nullptr");
516         return;
517     }
518 
519     if (isDataShareService_) {
520         if (!UnregObserver(uri, dataObserver)) {
521             LOG_ERROR("UnregisterObserver failed");
522         }
523         return;
524     }
525 
526     auto connection = dataShareConnection_;
527     if (connection == nullptr) {
528         LOG_ERROR("dataShareConnection_ is nullptr");
529         return;
530     }
531     auto proxy = connection->GetDataShareProxy();
532     if (proxy == nullptr) {
533         LOG_ERROR("dataShareConnection_->GetDataShareProxy() is nullptr");
534         return;
535     }
536     proxy->UnregisterObserver(uri, dataObserver);
537 }
538 
539 /**
540  * @brief Notifies the registered observers of a change to the data resource specified by Uri.
541  *
542  * @param uri, Indicates the path of the data to operate.
543  */
NotifyChange(const Uri & uri)544 void DataShareHelper::NotifyChange(const Uri &uri)
545 {
546     auto connection = dataShareConnection_;
547     if (connection == nullptr) {
548         LOG_ERROR("dataShareConnection_ is nullptr");
549         return;
550     }
551 
552     if (!connection->ConnectDataShareExtAbility(uri_, token_)) {
553         LOG_ERROR("dataShareProxy is nullptr");
554         return;
555     }
556 
557     auto proxy = connection->GetDataShareProxy();
558     if (proxy != nullptr) {
559         proxy->NotifyChange(uri);
560     }
561 }
562 
563 /**
564  * @brief Converts the given uri that refer to the data share into a normalized URI. A normalized URI can be used
565  * across devices, persisted, backed up, and restored. It can refer to the same item in the data share even if the
566  * context has changed. If you implement URI normalization for a data share, you must also implement
567  * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to any
568  * method that is called on the data share must require normalization verification and denormalization. The default
569  * implementation of this method returns null, indicating that this data share does not support URI normalization.
570  *
571  * @param uri Indicates the Uri object to normalize.
572  *
573  * @return Returns the normalized Uri object if the data share supports URI normalization; returns null otherwise.
574  */
NormalizeUri(Uri & uri)575 Uri DataShareHelper::NormalizeUri(Uri &uri)
576 {
577     Uri uriValue("");
578     auto connection = dataShareConnection_;
579     if (connection == nullptr) {
580         LOG_ERROR("dataShareConnection_ is nullptr");
581         return uriValue;
582     }
583 
584     if (!connection->ConnectDataShareExtAbility(uri_, token_)) {
585         LOG_ERROR("dataShareProxy is nullptr");
586         return uriValue;
587     }
588 
589     auto proxy = connection->GetDataShareProxy();
590     if (proxy != nullptr) {
591         uriValue = proxy->NormalizeUri(uri);
592     }
593     return uriValue;
594 }
595 
596 /**
597  * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one.
598  * The default implementation of this method returns the original URI passed to it.
599  *
600  * @param uri uri Indicates the Uri object to denormalize.
601  *
602  * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed to
603  * this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found in
604  * the current environment.
605  */
DenormalizeUri(Uri & uri)606 Uri DataShareHelper::DenormalizeUri(Uri &uri)
607 {
608     Uri uriValue("");
609     auto connection = dataShareConnection_;
610     if (connection == nullptr) {
611         LOG_ERROR("dataShareConnection_ is nullptr");
612         return uriValue;
613     }
614 
615     if (!connection->ConnectDataShareExtAbility(uri_, token_)) {
616         LOG_ERROR("dataShareProxy is nullptr");
617         return uriValue;
618     }
619 
620     auto proxy = connection->GetDataShareProxy();
621     if (proxy != nullptr) {
622         uriValue = proxy->DenormalizeUri(uri);
623     }
624     return uriValue;
625 }
626 
RegObserver(const Uri & uri,const sptr<AAFwk::IDataAbilityObserver> & dataObserver)627 bool DataShareHelper::RegObserver (const Uri &uri, const sptr<AAFwk::IDataAbilityObserver> &dataObserver)
628 {
629     auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
630     if (obsMgrClient == nullptr) {
631         LOG_ERROR("get DataObsMgrClient failed");
632         return false;
633     }
634     ErrCode ret = obsMgrClient->RegisterObserver(uri, dataObserver);
635     if (ret != ERR_OK) {
636         return false;
637     }
638     return true;
639 }
UnregObserver(const Uri & uri,const sptr<AAFwk::IDataAbilityObserver> & dataObserver)640 bool DataShareHelper::UnregObserver (const Uri &uri, const sptr<AAFwk::IDataAbilityObserver> &dataObserver)
641 {
642     auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance();
643     if (obsMgrClient == nullptr) {
644         LOG_ERROR("get DataObsMgrClient failed");
645         return false;
646     }
647     ErrCode ret = obsMgrClient->UnregisterObserver(uri, dataObserver);
648     if (ret != ERR_OK) {
649         LOG_ERROR("UnregisterObserver failed");
650         return false;
651     }
652     return true;
653 }
654 }  // namespace DataShare
655 }  // namespace OHOS