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