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