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