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