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