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