• 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 "data_ability_helper_impl.h"
17 
18 #include "ability_scheduler_interface.h"
19 #include "ability_thread.h"
20 #include "abs_shared_result_set.h"
21 #include "hitrace_meter.h"
22 #include "data_ability_observer_interface.h"
23 #include "data_ability_operation.h"
24 #include "data_ability_predicates.h"
25 #include "data_ability_result.h"
26 #include "hilog_wrapper.h"
27 #include "values_bucket.h"
28 
29 namespace OHOS {
30 namespace AppExecFwk {
31 std::string SchemeOhos = "dataability";
32 using IAbilityScheduler = OHOS::AAFwk::IAbilityScheduler;
33 using AbilityManagerClient = OHOS::AAFwk::AbilityManagerClient;
DataAbilityHelperImpl(const std::shared_ptr<Context> & context,const std::shared_ptr<Uri> & uri,const sptr<IAbilityScheduler> & dataAbilityProxy,bool tryBind)34 DataAbilityHelperImpl::DataAbilityHelperImpl(const std::shared_ptr<Context> &context, const std::shared_ptr<Uri> &uri,
35     const sptr<IAbilityScheduler> &dataAbilityProxy, bool tryBind)
36 {
37     token_ = context->GetToken();
38     context_ = std::weak_ptr<Context>(context);
39     uri_ = uri;
40     tryBind_ = tryBind;
41     dataAbilityProxy_ = dataAbilityProxy;
42 }
43 
DataAbilityHelperImpl(const std::shared_ptr<OHOS::AbilityRuntime::Context> & context,const std::shared_ptr<Uri> & uri,const sptr<IAbilityScheduler> & dataAbilityProxy,bool tryBind)44 DataAbilityHelperImpl::DataAbilityHelperImpl(const std::shared_ptr<OHOS::AbilityRuntime::Context> &context,
45     const std::shared_ptr<Uri> &uri, const sptr<IAbilityScheduler> &dataAbilityProxy, bool tryBind)
46 {
47     token_ = context->GetToken();
48     uri_ = uri;
49     tryBind_ = tryBind;
50     dataAbilityProxy_ = dataAbilityProxy;
51 }
52 
DataAbilityHelperImpl(const std::shared_ptr<Context> & context)53 DataAbilityHelperImpl::DataAbilityHelperImpl(const std::shared_ptr<Context> &context)
54 {
55     token_ = context->GetToken();
56     context_ = std::weak_ptr<Context>(context);
57 }
58 
DataAbilityHelperImpl(const sptr<IRemoteObject> & token,const std::shared_ptr<Uri> & uri,const sptr<AAFwk::IAbilityScheduler> & dataAbilityProxy)59 DataAbilityHelperImpl::DataAbilityHelperImpl(const sptr<IRemoteObject> &token, const std::shared_ptr<Uri> &uri,
60     const sptr<AAFwk::IAbilityScheduler> &dataAbilityProxy)
61 {
62     token_ = token;
63     uri_ = uri;
64     tryBind_ = false;
65     dataAbilityProxy_ = dataAbilityProxy;
66     isSystemCaller_ = true;
67 }
68 
DataAbilityHelperImpl(const sptr<IRemoteObject> & token)69 DataAbilityHelperImpl::DataAbilityHelperImpl(const sptr<IRemoteObject> &token)
70 {
71     token_ = token;
72     isSystemCaller_ = true;
73 }
74 
AddDataAbilityDeathRecipient(const sptr<IRemoteObject> & token)75 void DataAbilityHelperImpl::AddDataAbilityDeathRecipient(const sptr<IRemoteObject> &token)
76 {
77     if (token != nullptr && callerDeathRecipient_ != nullptr) {
78         HILOG_INFO("Remove death recipient.");
79         token->RemoveDeathRecipient(callerDeathRecipient_);
80     }
81     if (callerDeathRecipient_ == nullptr) {
82         std::weak_ptr<DataAbilityHelperImpl> thisWeakPtr(shared_from_this());
83         callerDeathRecipient_ =
84             new DataAbilityDeathRecipient([thisWeakPtr](const wptr<IRemoteObject> &remote) {
85                 auto DataAbilityHelperImpl = thisWeakPtr.lock();
86                 if (DataAbilityHelperImpl) {
87                     DataAbilityHelperImpl->OnSchedulerDied(remote);
88                 }
89             });
90     }
91     HILOG_INFO("Add death recipient.");
92     if (token == nullptr || !token->AddDeathRecipient(callerDeathRecipient_)) {
93         HILOG_ERROR("AddDeathRecipient failed.");
94     }
95 }
96 
OnSchedulerDied(const wptr<IRemoteObject> & remote)97 void DataAbilityHelperImpl::OnSchedulerDied(const wptr<IRemoteObject> &remote)
98 {
99     HILOG_INFO("On scheduler died.");
100     std::lock_guard<std::mutex> guard(lock_);
101     auto object = remote.promote();
102     object = nullptr;
103     dataAbilityProxy_ = nullptr;
104     uri_ = nullptr;
105 }
106 
107 /**
108  * @brief Creates a DataAbilityHelperImpl instance without specifying the Uri based on the given Context.
109  *
110  * @param context Indicates the Context object on OHOS.
111  *
112  * @return Returns the created DataAbilityHelperImpl instance where Uri is not specified.
113  */
Creator(const std::shared_ptr<Context> & context)114 std::shared_ptr<DataAbilityHelperImpl> DataAbilityHelperImpl::Creator(const std::shared_ptr<Context> &context)
115 {
116     if (context == nullptr) {
117         HILOG_ERROR("Input param invalid, context is nullptr.");
118         return nullptr;
119     }
120 
121     auto ptrDataAbilityHelperImpl = new (std::nothrow) DataAbilityHelperImpl(context);
122     if (ptrDataAbilityHelperImpl == nullptr) {
123         HILOG_ERROR("New DataAbilityHelperImpl failed.");
124         return nullptr;
125     }
126 
127     return std::shared_ptr<DataAbilityHelperImpl>(ptrDataAbilityHelperImpl);
128 }
129 
130 /**
131  * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship
132  * between the ability using the Data template (Data ability for short) and the associated client process in
133  * a DataAbilityHelperImpl instance.
134  *
135  * @param context Indicates the Context object on OHOS.
136  * @param uri Indicates the database table or disk file to operate.
137  * @param tryBind Specifies whether the exit of the corresponding Data ability process causes the exit of the
138  * client process.
139  *
140  * @return Returns the created DataAbilityHelperImpl instance.
141  */
Creator(const std::shared_ptr<Context> & context,const std::shared_ptr<Uri> & uri,const bool tryBind)142 std::shared_ptr<DataAbilityHelperImpl> DataAbilityHelperImpl::Creator(
143     const std::shared_ptr<Context> &context, const std::shared_ptr<Uri> &uri, const bool tryBind)
144 {
145     if (context == nullptr) {
146         HILOG_ERROR("Input param invalid, context is nullptr.");
147         return nullptr;
148     }
149 
150     if (!CheckUri(uri)) {
151         HILOG_ERROR("uri is invalid.");
152         return nullptr;
153     }
154 
155     sptr<IAbilityScheduler> dataAbilityProxy =
156         AbilityManagerClient::GetInstance()->AcquireDataAbility(*uri.get(), tryBind, context->GetToken());
157     if (dataAbilityProxy == nullptr) {
158         HILOG_ERROR("Acquire data ability failed.");
159         return nullptr;
160     }
161 
162     auto ptrDataAbilityHelperImpl = new (std::nothrow) DataAbilityHelperImpl(context, uri, dataAbilityProxy, tryBind);
163     if (ptrDataAbilityHelperImpl == nullptr) {
164         HILOG_ERROR("New DataAbilityHelperImpl failed.");
165         return nullptr;
166     }
167 
168     return std::shared_ptr<DataAbilityHelperImpl>(ptrDataAbilityHelperImpl);
169 }
170 
171 /**
172  * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship
173  * between the ability using the Data template (Data ability for short) and the associated client process in
174  * a DataAbilityHelperImpl instance.
175  *
176  * @param context Indicates the Context object on OHOS.
177  * @param uri Indicates the database table or disk file to operate.
178  * @param tryBind Specifies whether the exit of the corresponding Data ability process causes the exit of the
179  * client process.
180  *
181  * @return Returns the created DataAbilityHelperImpl instance.
182  */
Creator(const std::shared_ptr<OHOS::AbilityRuntime::Context> & context,const std::shared_ptr<Uri> & uri,const bool tryBind)183 std::shared_ptr<DataAbilityHelperImpl> DataAbilityHelperImpl::Creator(
184     const std::shared_ptr<OHOS::AbilityRuntime::Context> &context, const std::shared_ptr<Uri> &uri, const bool tryBind)
185 {
186     if (context == nullptr) {
187         HILOG_ERROR("Input param invalid, context is nullptr.");
188         return nullptr;
189     }
190 
191     if (!CheckUri(uri)) {
192         HILOG_ERROR("uri is invalid.");
193         return nullptr;
194     }
195 
196     sptr<IAbilityScheduler> dataAbilityProxy =
197         AbilityManagerClient::GetInstance()->AcquireDataAbility(*uri.get(), tryBind, context->GetToken());
198     if (dataAbilityProxy == nullptr) {
199         HILOG_ERROR("Acquire data ability failed.");
200         return nullptr;
201     }
202 
203     auto ptrDataAbilityHelperImpl = new (std::nothrow) DataAbilityHelperImpl(context, uri, dataAbilityProxy, tryBind);
204     if (ptrDataAbilityHelperImpl == nullptr) {
205         HILOG_ERROR("New DataAbilityHelperImpl failed.");
206         return nullptr;
207     }
208 
209     return std::shared_ptr<DataAbilityHelperImpl>(ptrDataAbilityHelperImpl);
210 }
211 
212 /**
213  * @brief Creates a DataAbilityHelperImpl instance without specifying the Uri based.
214  *
215  * @param token Indicates the System token.
216  *
217  * @return Returns the created DataAbilityHelperImpl instance where Uri is not specified.
218  */
Creator(const sptr<IRemoteObject> & token)219 std::shared_ptr<DataAbilityHelperImpl> DataAbilityHelperImpl::Creator(const sptr<IRemoteObject> &token)
220 {
221     if (token == nullptr) {
222         HILOG_ERROR("Input param invalid, token is nullptr.");
223         return nullptr;
224     }
225 
226     auto ptrDataAbilityHelperImpl = new (std::nothrow) DataAbilityHelperImpl(token);
227     if (ptrDataAbilityHelperImpl == nullptr) {
228         HILOG_ERROR("New DataAbilityHelperImpl failed.");
229         return nullptr;
230     }
231 
232     return std::shared_ptr<DataAbilityHelperImpl>(ptrDataAbilityHelperImpl);
233 }
234 
235 /**
236  * @brief You can use this method to specify the Uri of the data to operate and set the binding relationship
237  * between the ability using the Data template (Data ability for short) and the associated client process in
238  * a DataAbilityHelperImpl instance.
239  *
240  * @param token Indicates the System token.
241  * @param uri Indicates the database table or disk file to operate.
242  *
243  * @return Returns the created DataAbilityHelperImpl instance.
244  */
Creator(const sptr<IRemoteObject> & token,const std::shared_ptr<Uri> & uri)245 std::shared_ptr<DataAbilityHelperImpl> DataAbilityHelperImpl::Creator(
246     const sptr<IRemoteObject> &token, const std::shared_ptr<Uri> &uri)
247 {
248     if (token == nullptr) {
249         HILOG_ERROR("Input param invalid, token is nullptr.");
250         return nullptr;
251     }
252 
253     if (!CheckUri(uri)) {
254         HILOG_ERROR("uri is invalid.");
255         return nullptr;
256     }
257 
258     sptr<IAbilityScheduler> dataAbilityProxy =
259         AbilityManagerClient::GetInstance()->AcquireDataAbility(*uri.get(), false, token);
260     if (dataAbilityProxy == nullptr) {
261         HILOG_ERROR("Acquire data ability failed.");
262         return nullptr;
263     }
264 
265     auto ptrDataAbilityHelperImpl = new (std::nothrow) DataAbilityHelperImpl(token, uri, dataAbilityProxy);
266     if (ptrDataAbilityHelperImpl == nullptr) {
267         HILOG_ERROR("New DataAbilityHelperImpl failed.");
268         return nullptr;
269     }
270 
271     return std::shared_ptr<DataAbilityHelperImpl>(ptrDataAbilityHelperImpl);
272 }
273 
274 /**
275  * @brief Releases the client resource of the Data ability.
276  * You should call this method to releases client resource after the data operations are complete.
277  *
278  * @return Returns true if the resource is successfully released; returns false otherwise.
279  */
Release()280 bool DataAbilityHelperImpl::Release()
281 {
282     if (uri_ == nullptr) {
283         HILOG_ERROR("Release failed, uri_ is nullptr.");
284         return false;
285     }
286 
287     int err = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy_, token_);
288     if (err != ERR_OK) {
289         HILOG_ERROR("Release data ability failed, err = %{public}d.", err);
290         return false;
291     }
292 
293     return true;
294 }
295 
296 /**
297  * @brief Obtains the MIME types of files supported.
298  *
299  * @param uri Indicates the path of the files to obtain.
300  * @param mimeTypeFilter Indicates the MIME types of the files to obtain. This parameter cannot be null.
301  *
302  * @return Returns the matched MIME types. If there is no match, null is returned.
303  */
GetFileTypes(Uri & uri,const std::string & mimeTypeFilter)304 std::vector<std::string> DataAbilityHelperImpl::GetFileTypes(Uri &uri, const std::string &mimeTypeFilter)
305 {
306     std::vector<std::string> matchedMIMEs;
307     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
308     if (dataAbilityProxy == nullptr) {
309         HILOG_ERROR("Get data ability proxy failed.");
310         return matchedMIMEs;
311     }
312 
313     matchedMIMEs = dataAbilityProxy->GetFileTypes(uri, mimeTypeFilter);
314 
315     ReleaseDataAbility(dataAbilityProxy);
316     HILOG_INFO("Return matchedMIMEs size: %{public}zu.", matchedMIMEs.size());
317     return matchedMIMEs;
318 }
319 
320 /**
321  * @brief Opens a file in a specified remote path.
322  *
323  * @param uri Indicates the path of the file to open.
324  * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access
325  * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file,
326  * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data,
327  *  or "rwt" for read and write access that truncates any existing file.
328  *
329  * @return Returns the file descriptor.
330  */
OpenFile(Uri & uri,const std::string & mode)331 int DataAbilityHelperImpl::OpenFile(Uri &uri, const std::string &mode)
332 {
333     int fd = -1;
334     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
335     if (dataAbilityProxy == nullptr) {
336         HILOG_ERROR("Get data ability proxy failed.");
337         return fd;
338     }
339 
340     fd = dataAbilityProxy->OpenFile(uri, mode);
341 
342     ReleaseDataAbility(dataAbilityProxy);
343     HILOG_INFO("Return fd: %{public}d.", fd);
344     return fd;
345 }
346 
347 /**
348  * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets
349  * inside of their .hap.
350  *
351  * @param uri Indicates the path of the file to open.
352  * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access
353  * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file,
354  * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing
355  * data, or "rwt" for read and write access that truncates any existing file.
356  *
357  * @return Returns the RawFileDescriptor object containing file descriptor.
358  */
OpenRawFile(Uri & uri,const std::string & mode)359 int DataAbilityHelperImpl::OpenRawFile(Uri &uri, const std::string &mode)
360 {
361     int fd = -1;
362     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
363     if (dataAbilityProxy == nullptr) {
364         HILOG_ERROR("Get data ability proxy failed.");
365         return fd;
366     }
367 
368     fd = dataAbilityProxy->OpenRawFile(uri, mode);
369 
370     ReleaseDataAbility(dataAbilityProxy);
371     HILOG_INFO("Return fd: %{public}d.", fd);
372     return fd;
373 }
374 
375 /**
376  * @brief Inserts a single data record into the database.
377  *
378  * @param uri Indicates the path of the data to operate.
379  * @param value Indicates the data record to insert. If this parameter is null, a blank row will be inserted.
380  *
381  * @return Returns the index of the inserted data record.
382  */
Insert(Uri & uri,const NativeRdb::ValuesBucket & value)383 int DataAbilityHelperImpl::Insert(Uri &uri, const NativeRdb::ValuesBucket &value)
384 {
385     int index = -1;
386     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
387     if (dataAbilityProxy == nullptr) {
388         HILOG_ERROR("Get data ability proxy failed.");
389         return index;
390     }
391 
392     index = dataAbilityProxy->Insert(uri, value);
393 
394     ReleaseDataAbility(dataAbilityProxy);
395     HILOG_INFO("Return index: %{public}d.", index);
396     return index;
397 }
398 
Call(const Uri & uri,const std::string & method,const std::string & arg,const AppExecFwk::PacMap & pacMap)399 std::shared_ptr<AppExecFwk::PacMap> DataAbilityHelperImpl::Call(
400     const Uri &uri, const std::string &method, const std::string &arg, const AppExecFwk::PacMap &pacMap)
401 {
402     std::shared_ptr<AppExecFwk::PacMap> result = nullptr;
403     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
404     if (dataAbilityProxy == nullptr) {
405         HILOG_ERROR("Get data ability proxy failed.");
406         return result;
407     }
408 
409     result = dataAbilityProxy->Call(uri, method, arg, pacMap);
410 
411     ReleaseDataAbility(dataAbilityProxy);
412     HILOG_INFO("Return result is or not nullptr: %{public}d.", result == nullptr);
413     return result;
414 }
415 
416 /**
417  * @brief Updates data records in the database.
418  *
419  * @param uri Indicates the path of data to update.
420  * @param value Indicates the data to update. This parameter can be null.
421  * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null.
422  *
423  * @return Returns the number of data records updated.
424  */
Update(Uri & uri,const NativeRdb::ValuesBucket & value,const NativeRdb::DataAbilityPredicates & predicates)425 int DataAbilityHelperImpl::Update(
426     Uri &uri, const NativeRdb::ValuesBucket &value, const NativeRdb::DataAbilityPredicates &predicates)
427 {
428     int index = -1;
429     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
430     if (dataAbilityProxy == nullptr) {
431         HILOG_ERROR("Get data ability proxy failed.");
432         return index;
433     }
434 
435     index = dataAbilityProxy->Update(uri, value, predicates);
436 
437     ReleaseDataAbility(dataAbilityProxy);
438     HILOG_INFO("Return index: %{public}d.", index);
439     return index;
440 }
441 
442 /**
443  * @brief Deletes one or more data records from the database.
444  *
445  * @param uri Indicates the path of the data to operate.
446  * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null.
447  *
448  * @return Returns the number of data records deleted.
449  */
Delete(Uri & uri,const NativeRdb::DataAbilityPredicates & predicates)450 int DataAbilityHelperImpl::Delete(Uri &uri, const NativeRdb::DataAbilityPredicates &predicates)
451 {
452     int index = -1;
453     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
454     if (dataAbilityProxy == nullptr) {
455         HILOG_ERROR("Get data ability proxy failed.");
456         return index;
457     }
458 
459     index = dataAbilityProxy->Delete(uri, predicates);
460 
461     ReleaseDataAbility(dataAbilityProxy);
462     HILOG_INFO("Return index: %{public}d.", index);
463     return index;
464 }
465 
466 /**
467  * @brief Deletes one or more data records from the database.
468  *
469  * @param uri Indicates the path of data to query.
470  * @param columns Indicates the columns to query. If this parameter is null, all columns are queried.
471  * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null.
472  *
473  * @return Returns the query result.
474  */
Query(Uri & uri,std::vector<std::string> & columns,const NativeRdb::DataAbilityPredicates & predicates)475 std::shared_ptr<NativeRdb::AbsSharedResultSet> DataAbilityHelperImpl::Query(
476     Uri &uri, std::vector<std::string> &columns, const NativeRdb::DataAbilityPredicates &predicates)
477 {
478     std::shared_ptr<NativeRdb::AbsSharedResultSet> resultset = nullptr;
479     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
480     if (dataAbilityProxy == nullptr) {
481         HILOG_ERROR("Get data ability proxy failed.");
482         return resultset;
483     }
484 
485     resultset = dataAbilityProxy->Query(uri, columns, predicates);
486 
487     ReleaseDataAbility(dataAbilityProxy);
488     HILOG_DEBUG("Return resultset is or not nullptr: %{public}d.", resultset == nullptr);
489     return resultset;
490 }
491 
492 /**
493  * @brief Obtains the MIME type matching the data specified by the URI of the Data ability. This method should be
494  * implemented by a Data ability. Data abilities supports general data types, including text, HTML, and JPEG.
495  *
496  * @param uri Indicates the URI of the data.
497  *
498  * @return Returns the MIME type that matches the data specified by uri.
499  */
GetType(Uri & uri)500 std::string DataAbilityHelperImpl::GetType(Uri &uri)
501 {
502     std::string type;
503     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
504     if (dataAbilityProxy == nullptr) {
505         HILOG_ERROR("Get data ability proxy failed.");
506         return type;
507     }
508 
509     type = dataAbilityProxy->GetType(uri);
510 
511     ReleaseDataAbility(dataAbilityProxy);
512     HILOG_INFO("Return type: %{public}s.", type.c_str());
513     return type;
514 }
515 
516 /**
517  * @brief Reloads data in the database.
518  *
519  * @param uri Indicates the position where the data is to reload. This parameter is mandatory.
520  * @param extras Indicates the PacMap object containing the additional parameters to be passed in this call. This
521  * parameter can be null. If a custom Sequenceable object is put in the PacMap object and will be transferred across
522  * processes, you must call BasePacMap.setClassLoader(ClassLoader) to set a class loader for the custom object.
523  *
524  * @return Returns true if the data is successfully reloaded; returns false otherwise.
525  */
Reload(Uri & uri,const PacMap & extras)526 bool DataAbilityHelperImpl::Reload(Uri &uri, const PacMap &extras)
527 {
528     bool ret = false;
529     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
530     if (dataAbilityProxy == nullptr) {
531         HILOG_ERROR("Get data ability proxy failed.");
532         return ret;
533     }
534 
535     ret = dataAbilityProxy->Reload(uri, extras);
536 
537     ReleaseDataAbility(dataAbilityProxy);
538     HILOG_INFO("Return ret: %{public}d.", ret);
539     return ret;
540 }
541 
542 /**
543  * @brief Inserts multiple data records into the database.
544  *
545  * @param uri Indicates the path of the data to operate.
546  * @param values Indicates the data records to insert.
547  *
548  * @return Returns the number of data records inserted.
549  */
BatchInsert(Uri & uri,const std::vector<NativeRdb::ValuesBucket> & values)550 int DataAbilityHelperImpl::BatchInsert(Uri &uri, const std::vector<NativeRdb::ValuesBucket> &values)
551 {
552     int ret = -1;
553     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
554     if (dataAbilityProxy == nullptr) {
555         HILOG_ERROR("Get data ability proxy failed.");
556         return ret;
557     }
558 
559     ret = dataAbilityProxy->BatchInsert(uri, values);
560 
561     ReleaseDataAbility(dataAbilityProxy);
562     HILOG_INFO("Return ret: %{public}d.", ret);
563     return ret;
564 }
565 
CheckUriParam(const Uri & uri)566 bool DataAbilityHelperImpl::CheckUriParam(const Uri &uri)
567 {
568     Uri checkUri(uri.ToString());
569     if (!CheckOhosUri(checkUri)) {
570         HILOG_ERROR("Check ohos uri failed, uri: %{public}s.", uri.ToString().c_str());
571         return false;
572     }
573 
574     // do not directly use uri_ here, otherwise, it will probably crash.
575     std::vector<std::string> segments;
576     {
577         std::lock_guard<std::mutex> guard(lock_);
578         if (!uri_) {
579             HILOG_INFO("uri_ is nullptr, no need check.");
580             return true;
581         }
582 
583         if (!CheckOhosUri(*uri_)) {
584             HILOG_ERROR("Check ohos uri failed, uri_: %{public}s.", uri_->ToString().c_str());
585             return false;
586         }
587 
588         uri_->GetPathSegments(segments);
589     }
590 
591     std::vector<std::string> checkSegments;
592     checkUri.GetPathSegments(checkSegments);
593     if (checkSegments.empty() || segments.empty() || checkSegments[0] != segments[0]) {
594         HILOG_ERROR("The dataability in uri doesn't equal the one in uri_.");
595         return false;
596     }
597 
598     return true;
599 }
600 
CheckOhosUri(const Uri & uri)601 bool DataAbilityHelperImpl::CheckOhosUri(const Uri &uri)
602 {
603     Uri checkUri(uri.ToString());
604     if (checkUri.GetScheme() != SchemeOhos) {
605         HILOG_ERROR("Input uri is not a dataability one, uri: %{public}s.", uri.ToString().c_str());
606         return false;
607     }
608 
609     std::vector<std::string> segments;
610     checkUri.GetPathSegments(segments);
611     if (segments.empty()) {
612         HILOG_ERROR("There is no segments in the uri, uri: %{public}s.", uri.ToString().c_str());
613         return false;
614     }
615 
616     if (checkUri.GetPath() == "") {
617         HILOG_ERROR("The path in the uri is empty, uri: %{public}s.", uri.ToString().c_str());
618         return false;
619     }
620 
621     return true;
622 }
623 
624 /**
625  * @brief Registers an observer to DataObsMgr specified by the given Uri.
626  *
627  * @param uri, Indicates the path of the data to operate.
628  * @param dataObserver, Indicates the IDataAbilityObserver object.
629  */
RegisterObserver(const Uri & uri,const sptr<AAFwk::IDataAbilityObserver> & dataObserver)630 void DataAbilityHelperImpl::RegisterObserver(const Uri &uri, const sptr<AAFwk::IDataAbilityObserver> &dataObserver)
631 {
632     if (!CheckUriAndDataObserver(uri, dataObserver)) {
633         HILOG_ERROR("RegisterObserver param is invalid.");
634         return;
635     }
636 
637     Uri tmpUri(uri.ToString());
638 
639     std::lock_guard<std::mutex> lock_l(oplock_);
640     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = nullptr;
641     if (uri_ == nullptr) {
642         auto dataability = registerMap_.find(dataObserver);
643         if (dataability == registerMap_.end()) {
644             dataAbilityProxy = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_);
645             registerMap_.emplace(dataObserver, dataAbilityProxy);
646             uriMap_.emplace(dataObserver, tmpUri.GetPath());
647         } else {
648             auto path = uriMap_.find(dataObserver);
649             if (path == uriMap_.end()) {
650                 return;
651             }
652             if (path->second != tmpUri.GetPath()) {
653                 HILOG_ERROR("Input uri's path is not equal the one the observer used.");
654                 return;
655             }
656             dataAbilityProxy = dataability->second;
657         }
658     } else {
659         dataAbilityProxy = dataAbilityProxy_;
660     }
661 
662     if (dataAbilityProxy == nullptr) {
663         HILOG_ERROR("dataAbilityProxy is nullptr.");
664         registerMap_.erase(dataObserver);
665         uriMap_.erase(dataObserver);
666         return;
667     }
668     dataAbilityProxy->ScheduleRegisterObserver(uri, dataObserver);
669 }
670 
671 /**
672  * @brief Deregisters an observer used for DataObsMgr specified by the given Uri.
673  *
674  * @param uri, Indicates the path of the data to operate.
675  * @param dataObserver, Indicates the IDataAbilityObserver object.
676  */
UnregisterObserver(const Uri & uri,const sptr<AAFwk::IDataAbilityObserver> & dataObserver)677 void DataAbilityHelperImpl::UnregisterObserver(const Uri &uri, const sptr<AAFwk::IDataAbilityObserver> &dataObserver)
678 {
679     if (!CheckUriAndDataObserver(uri, dataObserver)) {
680         HILOG_ERROR("UnregisterObserver param is invalid.");
681         return;
682     }
683 
684     Uri tmpUri(uri.ToString());
685     std::lock_guard<std::mutex> lock_l(oplock_);
686     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = nullptr;
687     if (uri_ == nullptr) {
688         auto dataability = registerMap_.find(dataObserver);
689         if (dataability == registerMap_.end()) {
690             return;
691         }
692         auto path = uriMap_.find(dataObserver);
693         if (path == uriMap_.end()) {
694             return;
695         }
696         if (path->second != tmpUri.GetPath()) {
697             HILOG_ERROR("Input uri's path is not equal the one the observer used.");
698             return;
699         }
700         dataAbilityProxy = dataability->second;
701     } else {
702         dataAbilityProxy = dataAbilityProxy_;
703     }
704 
705     if (dataAbilityProxy == nullptr) {
706         HILOG_ERROR("dataAbilityProxy is nullptr.");
707         return;
708     }
709 
710     dataAbilityProxy->ScheduleUnregisterObserver(uri, dataObserver);
711     ReleaseDataAbility(dataAbilityProxy_);
712     if (uri_ == nullptr) {
713         dataAbilityProxy_ = nullptr;
714     }
715     registerMap_.erase(dataObserver);
716     uriMap_.erase(dataObserver);
717 }
718 
719 /**
720  * @brief Notifies the registered observers of a change to the data resource specified by Uri.
721  *
722  * @param uri, Indicates the path of the data to operate.
723  */
NotifyChange(const Uri & uri)724 void DataAbilityHelperImpl::NotifyChange(const Uri &uri)
725 {
726     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
727     if (dataAbilityProxy == nullptr) {
728         HILOG_ERROR("Get data ability proxy failed.");
729         return;
730     }
731 
732     dataAbilityProxy->ScheduleNotifyChange(uri);
733     ReleaseDataAbility(dataAbilityProxy);
734 }
735 
736 /**
737  * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used
738  * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if the
739  * context has changed. If you implement URI normalization for a Data ability, you must also implement
740  * denormalizeUri(ohos.utils.net.Uri) to enable URI denormalization. After this feature is enabled, URIs passed to any
741  * method that is called on the Data ability must require normalization verification and denormalization. The default
742  * implementation of this method returns null, indicating that this Data ability does not support URI normalization.
743  *
744  * @param uri Indicates the Uri object to normalize.
745  *
746  * @return Returns the normalized Uri object if the Data ability supports URI normalization; returns null otherwise.
747  */
NormalizeUri(Uri & uri)748 Uri DataAbilityHelperImpl::NormalizeUri(Uri &uri)
749 {
750     Uri urivalue("");
751     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
752     if (dataAbilityProxy == nullptr) {
753         HILOG_ERROR("Get data ability proxy failed.");
754         return urivalue;
755     }
756 
757     urivalue = dataAbilityProxy->NormalizeUri(uri);
758 
759     ReleaseDataAbility(dataAbilityProxy);
760     HILOG_INFO("Return uri: %{public}s.", urivalue.ToString().c_str());
761     return urivalue;
762 }
763 
764 /**
765  * @brief Converts the given normalized uri generated by normalizeUri(ohos.utils.net.Uri) into a denormalized one.
766  * The default implementation of this method returns the original URI passed to it.
767  *
768  * @param uri uri Indicates the Uri object to denormalize.
769  *
770  * @return Returns the denormalized Uri object if the denormalization is successful; returns the original Uri passed to
771  * this method if there is nothing to do; returns null if the data identified by the original Uri cannot be found in the
772  * current environment.
773  */
DenormalizeUri(Uri & uri)774 Uri DataAbilityHelperImpl::DenormalizeUri(Uri &uri)
775 {
776     Uri urivalue("");
777     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri);
778     if (dataAbilityProxy == nullptr) {
779         HILOG_ERROR("Get data ability proxy failed.");
780         return urivalue;
781     }
782 
783     urivalue = dataAbilityProxy->DenormalizeUri(uri);
784 
785     ReleaseDataAbility(dataAbilityProxy);
786     HILOG_INFO("Return uri: %{public}s.", urivalue.ToString().c_str());
787     return urivalue;
788 }
789 
ExecuteBatch(const Uri & uri,const std::vector<std::shared_ptr<DataAbilityOperation>> & operations)790 std::vector<std::shared_ptr<DataAbilityResult>> DataAbilityHelperImpl::ExecuteBatch(
791     const Uri &uri, const std::vector<std::shared_ptr<DataAbilityOperation>> &operations)
792 {
793     std::vector<std::shared_ptr<DataAbilityResult>> results;
794     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = GetDataAbilityProxy(uri, false);
795     if (dataAbilityProxy == nullptr) {
796         HILOG_ERROR("Get data ability proxy failed.");
797         return results;
798     }
799 
800     results = dataAbilityProxy->ExecuteBatch(operations);
801 
802     ReleaseDataAbility(dataAbilityProxy);
803     HILOG_INFO("Return results size: %{public}zu.", results.size());
804     return results;
805 }
806 
GetDataAbilityProxy(const Uri & uri,bool addDeathRecipient)807 sptr<AAFwk::IAbilityScheduler> DataAbilityHelperImpl::GetDataAbilityProxy(const Uri &uri, bool addDeathRecipient)
808 {
809     if (!CheckUriParam(uri)) {
810         HILOG_ERROR("Check uri param failed.");
811         return nullptr;
812     }
813     // if uri_ is nullptr, it indicates the operation(such as insert, delete and so on) is temporary,
814     // so, we need acquire the dataability before the operation.
815     sptr<AAFwk::IAbilityScheduler> dataAbilityProxy = dataAbilityProxy_;
816     if (uri_ == nullptr) {
817         HILOG_INFO("The uri_ is nullptr, need acquire data ability.");
818         dataAbilityProxy = AbilityManagerClient::GetInstance()->AcquireDataAbility(uri, tryBind_, token_);
819         if (dataAbilityProxy == nullptr) {
820             HILOG_ERROR("Acquire data ability failed.");
821             return nullptr;
822         }
823         if (addDeathRecipient && isSystemCaller_) {
824             AddDataAbilityDeathRecipient(dataAbilityProxy->AsObject());
825         }
826     }
827     return dataAbilityProxy;
828 }
829 
ReleaseDataAbility(sptr<AAFwk::IAbilityScheduler> dataAbilityProxy)830 void DataAbilityHelperImpl::ReleaseDataAbility(sptr<AAFwk::IAbilityScheduler> dataAbilityProxy)
831 {
832     // if uri_ is nullptr, it indicates the operation(such as insert, delete and so on) is temporary,
833     // so, we need release the dataability after the operation.
834     HILOG_INFO("ReleaseDataAbility start.");
835     if (!uri_ && dataAbilityProxy && token_) {
836         int ret = AbilityManagerClient::GetInstance()->ReleaseDataAbility(dataAbilityProxy, token_);
837         HILOG_INFO("Release data ability, ret: %{public}d.", ret);
838     }
839     HILOG_INFO("ReleaseDataAbility end.");
840 }
841 
CheckUri(const std::shared_ptr<Uri> & uri)842 bool DataAbilityHelperImpl::CheckUri(const std::shared_ptr<Uri> &uri)
843 {
844     if (uri == nullptr) {
845         HILOG_ERROR("Input param invalid, uri is nullptr.");
846         return false;
847     }
848 
849     if (uri->GetScheme() != SchemeOhos) {
850         HILOG_ERROR("Input param invalid, the uri is not dataability, Scheme: %{private}s.", uri->GetScheme().c_str());
851         return false;
852     }
853 
854     return true;
855 }
856 
CheckUriAndDataObserver(const Uri & uri,const sptr<AAFwk::IDataAbilityObserver> & dataObserver)857 bool DataAbilityHelperImpl::CheckUriAndDataObserver(const Uri &uri,
858     const sptr<AAFwk::IDataAbilityObserver> &dataObserver)
859 {
860     if (!CheckUriParam(uri)) {
861         HILOG_ERROR("Check uri param failed.");
862         return false;
863     }
864 
865     if (dataObserver == nullptr) {
866         HILOG_ERROR("Input param invalid, dataObserver is nullptr.");
867         return false;
868     }
869 
870     return true;
871 }
872 
OnRemoteDied(const wptr<IRemoteObject> & remote)873 void DataAbilityDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
874 {
875     HILOG_INFO("recv DataAbilityDeathRecipient death notice.");
876     if (handler_) {
877         handler_(remote);
878     }
879     HILOG_INFO("OnRemoteDied end.");
880 }
881 
DataAbilityDeathRecipient(RemoteDiedHandler handler)882 DataAbilityDeathRecipient::DataAbilityDeathRecipient(RemoteDiedHandler handler) : handler_(handler)
883 {}
884 
~DataAbilityDeathRecipient()885 DataAbilityDeathRecipient::~DataAbilityDeathRecipient()
886 {}
887 }  // namespace AppExecFwk
888 }  // namespace OHOS
889 
890