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 #define LOG_TAG "UdmfServiceImpl"
16
17 #include "udmf_service_impl.h"
18
19 #include "iservice_registry.h"
20
21 #include "checker_manager.h"
22 #include "dfx_types.h"
23 #include "distributed_kv_data_manager.h"
24 #include "file.h"
25 #include "lifecycle/lifecycle_manager.h"
26 #include "log_print.h"
27 #include "preprocess_utils.h"
28 #include "reporter.h"
29 #include "uri_permission_manager.h"
30 #include "uri.h"
31 #include "utd/custom_utd_installer.h"
32
33 namespace OHOS {
34 namespace UDMF {
35 using FeatureSystem = DistributedData::FeatureSystem;
36 using UdmfBehaviourMsg = OHOS::DistributedDataDfx::UdmfBehaviourMsg;
37 using Reporter = OHOS::DistributedDataDfx::Reporter;
38 constexpr const char *DRAG_AUTHORIZED_PROCESSES[] = {"msdp_sa", "collaboration_service"};
39 constexpr const char *DATA_PREFIX = "udmf://";
40 __attribute__((used)) UdmfServiceImpl::Factory UdmfServiceImpl::factory_;
Factory()41 UdmfServiceImpl::Factory::Factory()
42 {
43 ZLOGI("Register udmf creator!");
44 FeatureSystem::GetInstance().RegisterCreator("udmf", [this]() {
45 if (product_ == nullptr) {
46 product_ = std::make_shared<UdmfServiceImpl>();
47 }
48 return product_;
49 }, FeatureSystem::BIND_NOW);
50 staticActs_ = std::make_shared<UdmfStatic>();
51 FeatureSystem::GetInstance().RegisterStaticActs("udmf", staticActs_);
52 }
53
~Factory()54 UdmfServiceImpl::Factory::~Factory()
55 {
56 product_ = nullptr;
57 }
58
UdmfServiceImpl()59 UdmfServiceImpl::UdmfServiceImpl()
60 {
61 CheckerManager::GetInstance().LoadCheckers();
62 }
63
SetData(CustomOption & option,UnifiedData & unifiedData,std::string & key)64 int32_t UdmfServiceImpl::SetData(CustomOption &option, UnifiedData &unifiedData, std::string &key)
65 {
66 ZLOGD("start");
67 int32_t res = E_OK;
68 UdmfBehaviourMsg msg;
69 auto find = UD_INTENTION_MAP.find(option.intention);
70 msg.channel = find == UD_INTENTION_MAP.end() ? "invalid" : find->second;
71 msg.operation = "insert";
72 std::string bundleName;
73 if (!PreProcessUtils::GetHapBundleNameByToken(option.tokenId, bundleName)) {
74 msg.appId = "unknown";
75 res = E_ERROR;
76 } else {
77 msg.appId = bundleName;
78 res = SaveData(option, unifiedData, key);
79 }
80 auto errFind = ERROR_MAP.find(res);
81 msg.result = errFind == ERROR_MAP.end() ? "E_ERROR" : errFind->second;
82 msg.dataType = unifiedData.GetTypes();
83 msg.dataSize = unifiedData.GetSize();
84 Reporter::GetInstance()->BehaviourReporter()->UDMFReport(msg);
85 return res;
86 }
87
SaveData(CustomOption & option,UnifiedData & unifiedData,std::string & key)88 int32_t UdmfServiceImpl::SaveData(CustomOption &option, UnifiedData &unifiedData, std::string &key)
89 {
90 if (!unifiedData.IsValid()) {
91 ZLOGE("UnifiedData is invalid.");
92 return E_INVALID_PARAMETERS;
93 }
94
95 if (!UnifiedDataUtils::IsValidIntention(option.intention)) {
96 ZLOGE("Invalid parameters intention: %{public}d.", option.intention);
97 return E_INVALID_PARAMETERS;
98 }
99
100 // imput runtime info before put it into store and save one privilege
101 if (PreProcessUtils::RuntimeDataImputation(unifiedData, option) != E_OK) {
102 ZLOGE("Imputation failed");
103 return E_ERROR;
104 }
105
106 std::string intention = unifiedData.GetRuntime()->key.intention;
107 if (intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) {
108 int32_t ret = PreProcessUtils::SetRemoteUri(option.tokenId, unifiedData);
109 if (ret != E_OK) {
110 ZLOGE("SetRemoteUri failed, ret: %{public}d.", ret);
111 return ret;
112 }
113 }
114
115 for (const auto &record : unifiedData.GetRecords()) {
116 record->SetUid(PreProcessUtils::GenerateId());
117 }
118
119 auto store = StoreCache::GetInstance().GetStore(intention);
120 if (store == nullptr) {
121 ZLOGE("Get store failed, intention: %{public}s.", intention.c_str());
122 return E_DB_ERROR;
123 }
124
125 if (!UnifiedDataUtils::IsPersist(intention) && store->Clear() != E_OK) {
126 ZLOGE("Clear store failed, intention: %{public}s.", intention.c_str());
127 return E_DB_ERROR;
128 }
129
130 if (store->Put(unifiedData) != E_OK) {
131 ZLOGE("Put unified data failed, intention: %{public}s.", intention.c_str());
132 return E_DB_ERROR;
133 }
134 key = unifiedData.GetRuntime()->key.GetUnifiedKey();
135 ZLOGD("Put unified data successful, key: %{public}s.", key.c_str());
136 return E_OK;
137 }
138
GetData(const QueryOption & query,UnifiedData & unifiedData)139 int32_t UdmfServiceImpl::GetData(const QueryOption &query, UnifiedData &unifiedData)
140 {
141 ZLOGD("start");
142 int32_t res = E_OK;
143 UdmfBehaviourMsg msg;
144 auto find = UD_INTENTION_MAP.find(query.intention);
145 msg.channel = find == UD_INTENTION_MAP.end() ? "invalid" : find->second;
146 msg.operation = "insert";
147 std::string bundleName;
148 if (!PreProcessUtils::GetHapBundleNameByToken(query.tokenId, bundleName)) {
149 msg.appId = "unknown";
150 res = E_ERROR;
151 } else {
152 msg.appId = bundleName;
153 res = RetrieveData(query, unifiedData);
154 }
155 auto errFind = ERROR_MAP.find(res);
156 msg.result = errFind == ERROR_MAP.end() ? "E_ERROR" : errFind->second;
157 msg.dataType = unifiedData.GetTypes();
158 msg.dataSize = unifiedData.GetSize();
159 Reporter::GetInstance()->BehaviourReporter()->UDMFReport(msg);
160 return res;
161 }
162
RetrieveData(const QueryOption & query,UnifiedData & unifiedData)163 int32_t UdmfServiceImpl::RetrieveData(const QueryOption &query, UnifiedData &unifiedData)
164 {
165 UnifiedKey key(query.key);
166 if (!key.IsValid()) {
167 ZLOGE("Unified key: %{public}s is invalid.", query.key.c_str());
168 return E_INVALID_PARAMETERS;
169 }
170 auto store = StoreCache::GetInstance().GetStore(key.intention);
171 if (store == nullptr) {
172 ZLOGE("Get store failed, intention: %{public}s.", key.intention.c_str());
173 return E_DB_ERROR;
174 }
175 int32_t res = store->Get(query.key, unifiedData);
176 if (res != E_OK) {
177 ZLOGE("Get data from store failed, res: %{public}d, key: %{public}s.", res, query.key.c_str());
178 return res;
179 }
180
181 if (!unifiedData.IsComplete()) {
182 ZLOGE("Get data from DB is incomplete, key: %{public}s.", query.key.c_str());
183 return E_NOT_FOUND;
184 }
185
186 CheckerManager::CheckInfo info;
187 info.tokenId = query.tokenId;
188 std::shared_ptr<Runtime> runtime = unifiedData.GetRuntime();
189 if (runtime == nullptr) {
190 return E_DB_ERROR;
191 }
192 if (!CheckerManager::GetInstance().IsValid(runtime->privileges, info) && !IsPermissionInCache(query)) {
193 return E_NO_PERMISSION;
194 }
195
196 if (key.intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) {
197 int32_t ret = ProcessUri(query, unifiedData);
198 if (ret != E_OK) {
199 ZLOGE("DragUriProcessing failed. ret=%{public}d", ret);
200 return E_NO_PERMISSION;
201 }
202 }
203
204 if (LifeCycleManager::GetInstance().OnGot(key) != E_OK) {
205 ZLOGE("Remove data failed, intention: %{public}s.", key.intention.c_str());
206 return E_DB_ERROR;
207 }
208 privilegeCache_.erase(query.key);
209
210 PreProcessUtils::SetRemoteData(unifiedData);
211 return E_OK;
212 }
213
IsPermissionInCache(const QueryOption & query)214 bool UdmfServiceImpl::IsPermissionInCache(const QueryOption &query)
215 {
216 auto iter = privilegeCache_.find(query.key);
217 if (iter != privilegeCache_.end() && iter->second.tokenId == query.tokenId) {
218 return true;
219 }
220 return false;
221 }
222
ProcessUri(const QueryOption & query,UnifiedData & unifiedData)223 int32_t UdmfServiceImpl::ProcessUri(const QueryOption &query, UnifiedData &unifiedData)
224 {
225 std::string localDeviceId = PreProcessUtils::GetLocalDeviceId();
226 auto records = unifiedData.GetRecords();
227 if (unifiedData.GetRuntime() == nullptr) {
228 return E_DB_ERROR;
229 }
230 std::string sourceDeviceId = unifiedData.GetRuntime()->deviceId;
231 if (localDeviceId != sourceDeviceId) {
232 SetRemoteUri(query, records);
233 }
234
235 std::string bundleName;
236 if (!PreProcessUtils::GetHapBundleNameByToken(query.tokenId, bundleName)) {
237 ZLOGE("GetHapBundleNameByToken fail, key=%{public}s, tokenId=%{private}d.", query.key.c_str(), query.tokenId);
238 return E_ERROR;
239 }
240 for (auto record : records) {
241 if (record != nullptr && PreProcessUtils::IsFileType(record->GetType())) {
242 auto file = static_cast<File *>(record.get());
243 if (file->GetUri().empty()) {
244 ZLOGW("Get uri is empty, key=%{public}s.", query.key.c_str());
245 continue;
246 }
247 Uri uri(file->GetUri());
248 if (uri.GetAuthority().empty()) {
249 ZLOGW("Get authority is empty, key=%{public}s.", query.key.c_str());
250 continue;
251 }
252 if (localDeviceId == sourceDeviceId && bundleName == unifiedData.GetRuntime()->sourcePackage) {
253 ZLOGW("No need to grant uri permissions, bundleName=%{public}s.", bundleName.c_str());
254 continue;
255 }
256 if (UriPermissionManager::GetInstance().GrantUriPermission(file->GetUri(), bundleName) != E_OK) {
257 ZLOGE("GrantUriPermission fail, uriAuthority=%{public}s, bundleName=%{public}s, key=%{public}s.",
258 uri.GetAuthority().c_str(), bundleName.c_str(), query.key.c_str());
259 return E_NO_PERMISSION;
260 }
261 }
262 }
263 return E_OK;
264 }
265
SetRemoteUri(const QueryOption & query,std::vector<std::shared_ptr<UnifiedRecord>> & records)266 void UdmfServiceImpl::SetRemoteUri(const QueryOption &query, std::vector<std::shared_ptr<UnifiedRecord>> &records)
267 {
268 for (auto record : records) {
269 if (record != nullptr && PreProcessUtils::IsFileType(record->GetType())) {
270 auto file = static_cast<File *>(record.get());
271 std::string remoteUri = file->GetRemoteUri();
272 if (remoteUri.empty()) {
273 ZLOGW("Get remoteUri is empyt, key=%{public}s.", query.key.c_str());
274 continue;
275 }
276 file->SetUri(remoteUri); // cross dev, need dis path.
277 }
278 }
279 }
280
GetBatchData(const QueryOption & query,std::vector<UnifiedData> & unifiedDataSet)281 int32_t UdmfServiceImpl::GetBatchData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet)
282 {
283 ZLOGD("start");
284 std::vector<UnifiedData> dataSet;
285 std::shared_ptr<Store> store;
286 auto status = QueryDataCommon(query, dataSet, store);
287 if (status != E_OK) {
288 ZLOGE("QueryDataCommon failed.");
289 return status;
290 }
291 if (dataSet.empty()) {
292 ZLOGW("DataSet has no data, key: %{public}s, intention: %{public}d.", query.key.c_str(), query.intention);
293 return E_OK;
294 }
295 for (auto &data : dataSet) {
296 PreProcessUtils::SetRemoteData(data);
297 unifiedDataSet.push_back(data);
298 }
299 return E_OK;
300 }
301
UpdateData(const QueryOption & query,UnifiedData & unifiedData)302 int32_t UdmfServiceImpl::UpdateData(const QueryOption &query, UnifiedData &unifiedData)
303 {
304 ZLOGD("start");
305 if (!unifiedData.IsValid()) {
306 ZLOGE("UnifiedData is invalid.");
307 return E_INVALID_PARAMETERS;
308 }
309
310 UnifiedKey key(query.key);
311 if (!key.IsValid()) {
312 ZLOGE("Unified key: %{public}s is invalid.", query.key.c_str());
313 return E_INVALID_PARAMETERS;
314 }
315 auto store = StoreCache::GetInstance().GetStore(key.intention);
316 if (store == nullptr) {
317 ZLOGE("Get store failed, intention: %{public}s.", key.intention.c_str());
318 return E_DB_ERROR;
319 }
320
321 UnifiedData data;
322 int32_t res = store->Get(query.key, data);
323 if (res != E_OK) {
324 ZLOGE("Get data from store failed, intention: %{public}s.", key.intention.c_str());
325 return res;
326 }
327 if (data.IsEmpty()) {
328 ZLOGE("Invalid parameter, unified data has no record; intention: %{public}s.", key.intention.c_str());
329 return E_INVALID_PARAMETERS;
330 }
331 std::shared_ptr<Runtime> runtime = data.GetRuntime();
332 if (runtime == nullptr) {
333 return E_DB_ERROR;
334 }
335 runtime->lastModifiedTime = PreProcessUtils::GetTimestamp();
336 unifiedData.SetRuntime(*runtime);
337 for (auto &record : unifiedData.GetRecords()) {
338 record->SetUid(PreProcessUtils::GenerateId());
339 }
340 if (store->Update(unifiedData) != E_OK) {
341 ZLOGE("Update unified data failed, intention: %{public}s.", key.intention.c_str());
342 return E_DB_ERROR;
343 }
344 return E_OK;
345 }
346
DeleteData(const QueryOption & query,std::vector<UnifiedData> & unifiedDataSet)347 int32_t UdmfServiceImpl::DeleteData(const QueryOption &query, std::vector<UnifiedData> &unifiedDataSet)
348 {
349 ZLOGD("start");
350 std::vector<UnifiedData> dataSet;
351 std::shared_ptr<Store> store;
352 auto status = QueryDataCommon(query, dataSet, store);
353 if (status != E_OK) {
354 ZLOGE("QueryDataCommon failed.");
355 return status;
356 }
357 if (dataSet.empty()) {
358 ZLOGW("DataSet has no data, key: %{public}s, intention: %{public}d.", query.key.c_str(), query.intention);
359 return E_OK;
360 }
361 std::shared_ptr<Runtime> runtime;
362 std::vector<std::string> deleteKeys;
363 for (const auto &data : dataSet) {
364 runtime = data.GetRuntime();
365 if (runtime == nullptr) {
366 return E_DB_ERROR;
367 }
368 unifiedDataSet.push_back(data);
369 deleteKeys.push_back(runtime->key.key);
370 }
371 if (store->DeleteBatch(deleteKeys) != E_OK) {
372 ZLOGE("Remove data failed.");
373 return E_DB_ERROR;
374 }
375 return E_OK;
376 }
377
GetSummary(const QueryOption & query,Summary & summary)378 int32_t UdmfServiceImpl::GetSummary(const QueryOption &query, Summary &summary)
379 {
380 ZLOGD("start");
381 UnifiedKey key(query.key);
382 if (!key.IsValid()) {
383 ZLOGE("Unified key: %{public}s is invalid.", query.key.c_str());
384 return E_INVALID_PARAMETERS;
385 }
386
387 auto store = StoreCache::GetInstance().GetStore(key.intention);
388 if (store == nullptr) {
389 ZLOGE("Get store failed, intention: %{public}s.", key.intention.c_str());
390 return E_DB_ERROR;
391 }
392
393 if (store->GetSummary(query.key, summary) != E_OK) {
394 ZLOGE("Store get summary failed, intention: %{public}s.", key.intention.c_str());
395 return E_DB_ERROR;
396 }
397 return E_OK;
398 }
399
AddPrivilege(const QueryOption & query,Privilege & privilege)400 int32_t UdmfServiceImpl::AddPrivilege(const QueryOption &query, Privilege &privilege)
401 {
402 ZLOGD("start");
403 UnifiedKey key(query.key);
404 if (!key.IsValid()) {
405 ZLOGE("Unified key: %{public}s is invalid.", query.key.c_str());
406 return E_INVALID_PARAMETERS;
407 }
408
409 std::string processName;
410 if (!PreProcessUtils::GetNativeProcessNameByToken(query.tokenId, processName)) {
411 return E_ERROR;
412 }
413
414 if (key.intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) {
415 if (find(DRAG_AUTHORIZED_PROCESSES, std::end(DRAG_AUTHORIZED_PROCESSES), processName) ==
416 std::end(DRAG_AUTHORIZED_PROCESSES)) {
417 ZLOGE("Process: %{public}s has no permission to intention: drag", processName.c_str());
418 return E_NO_PERMISSION;
419 }
420 } else {
421 ZLOGE("Intention: %{public}s has no authorized processes", key.intention.c_str());
422 return E_NO_PERMISSION;
423 }
424
425 auto store = StoreCache::GetInstance().GetStore(key.intention);
426 if (store == nullptr) {
427 ZLOGE("Get store failed, intention: %{public}s.", key.intention.c_str());
428 return E_DB_ERROR;
429 }
430
431 UnifiedData data;
432 int32_t res = store->Get(query.key, data);
433 if (res == E_NOT_FOUND) {
434 privilegeCache_[query.key] = privilege;
435 ZLOGW("Add privilege in cache, key: %{public}s.", query.key.c_str());
436 return E_OK;
437 }
438 if (res != E_OK) {
439 ZLOGE("Get data from store failed, res:%{public}d,intention: %{public}s.", res, key.intention.c_str());
440 return res;
441 }
442 if (data.GetRuntime() == nullptr) {
443 return E_DB_ERROR;
444 }
445 data.GetRuntime()->privileges.emplace_back(privilege);
446 if (store->Update(data) != E_OK) {
447 ZLOGE("Update unified data failed, intention: %{public}s.", key.intention.c_str());
448 return E_DB_ERROR;
449 }
450 return E_OK;
451 }
452
Sync(const QueryOption & query,const std::vector<std::string> & devices)453 int32_t UdmfServiceImpl::Sync(const QueryOption &query, const std::vector<std::string> &devices)
454 {
455 ZLOGD("start");
456 UnifiedKey key(query.key);
457 if (!key.IsValid()) {
458 ZLOGE("Unified key: %{public}s is invalid.", query.key.c_str());
459 return E_INVALID_PARAMETERS;
460 }
461
462 auto store = StoreCache::GetInstance().GetStore(key.intention);
463 if (store == nullptr) {
464 ZLOGE("Get store failed, intention: %{public}s.", key.intention.c_str());
465 return E_DB_ERROR;
466 }
467
468 if (store->Sync(devices) != E_OK) {
469 ZLOGE("Store sync failed, intention: %{public}s.", key.intention.c_str());
470 return E_DB_ERROR;
471 }
472 return E_OK;
473 }
474
OnInitialize()475 int32_t UdmfServiceImpl::OnInitialize()
476 {
477 ZLOGD("start");
478 Status status = LifeCycleManager::GetInstance().OnStart();
479 if (status != E_OK) {
480 ZLOGE("OnStart execute failed, status: %{public}d", status);
481 }
482 status = LifeCycleManager::GetInstance().StartLifeCycleTimer();
483 if (status != E_OK) {
484 ZLOGE("StartLifeCycleTimer start failed, status: %{public}d", status);
485 }
486 return DistributedData::FeatureSystem::STUB_SUCCESS;
487 }
488
QueryDataCommon(const QueryOption & query,std::vector<UnifiedData> & dataSet,std::shared_ptr<Store> & store)489 int32_t UdmfServiceImpl::QueryDataCommon(
490 const QueryOption &query, std::vector<UnifiedData> &dataSet, std::shared_ptr<Store> &store)
491 {
492 auto find = UD_INTENTION_MAP.find(query.intention);
493 std::string intention = find == UD_INTENTION_MAP.end() ? intention : find->second;
494 if (!UnifiedDataUtils::IsValidOptions(query.key, intention)) {
495 ZLOGE("Unified key: %{public}s and intention: %{public}s is invalid.", query.key.c_str(), intention.c_str());
496 return E_INVALID_PARAMETERS;
497 }
498 std::string dataPrefix = DATA_PREFIX + intention;
499 UnifiedKey key(query.key);
500 key.IsValid();
501 if (intention.empty()) {
502 dataPrefix = key.key;
503 intention = key.intention;
504 }
505 ZLOGD("dataPrefix = %{public}s, intention: %{public}s.", dataPrefix.c_str(), intention.c_str());
506 store = StoreCache::GetInstance().GetStore(intention);
507 if (store == nullptr) {
508 ZLOGE("Get store failed, intention: %{public}s.", intention.c_str());
509 return E_DB_ERROR;
510 }
511 if (store->GetBatchData(dataPrefix, dataSet) != E_OK) {
512 ZLOGE("Get dataSet failed, dataPrefix: %{public}s.", dataPrefix.c_str());
513 return E_DB_ERROR;
514 }
515 return E_OK;
516 }
517
OnBind(const BindInfo & bindInfo)518 int32_t UdmfServiceImpl::OnBind(const BindInfo &bindInfo)
519 {
520 executors_ = bindInfo.executors;
521 StoreCache::GetInstance().SetThreadPool(bindInfo.executors);
522 LifeCycleManager::GetInstance().SetThreadPool(bindInfo.executors);
523 return 0;
524 }
525
OnAppInstall(const std::string & bundleName,int32_t user,int32_t index)526 int32_t UdmfServiceImpl::UdmfStatic::OnAppInstall(const std::string &bundleName, int32_t user,
527 int32_t index)
528 {
529 ZLOGD("Bundle: %{public}s installed.", bundleName.c_str());
530 auto status = CustomUtdInstaller::GetInstance().InstallUtd(bundleName, user);
531 if (status != E_OK) {
532 ZLOGE("Install Utd failed, bundleName: %{public}s, status: %{public}d", bundleName.c_str(), status);
533 }
534 return status;
535 }
536
OnAppUpdate(const std::string & bundleName,int32_t user,int32_t index)537 int32_t UdmfServiceImpl::UdmfStatic::OnAppUpdate(const std::string &bundleName, int32_t user,
538 int32_t index)
539 {
540 ZLOGD("Bundle: %{public}s Update.", bundleName.c_str());
541 auto status = CustomUtdInstaller::GetInstance().UninstallUtd(bundleName, user);
542 if (status != E_OK) {
543 ZLOGE("Uninstall utd failed, bundleName: %{public}s, status: %{public}d.", bundleName.c_str(), status);
544 return status;
545 }
546 status = CustomUtdInstaller::GetInstance().InstallUtd(bundleName, user);
547 if (status != E_OK) {
548 ZLOGE("Install utd failed, bundleName: %{public}s, status: %{public}d.", bundleName.c_str(), status);
549 }
550 return status;
551 }
552
OnAppUninstall(const std::string & bundleName,int32_t user,int32_t index)553 int32_t UdmfServiceImpl::UdmfStatic::OnAppUninstall(const std::string &bundleName, int32_t user,
554 int32_t index)
555 {
556 ZLOGD("Bundle: %{public}s uninstalled.", bundleName.c_str());
557 auto status = CustomUtdInstaller::GetInstance().UninstallUtd(bundleName, user);
558 if (status != E_OK) {
559 ZLOGE("Uninstall utd failed, bundleName: %{public}s, status: %{public}d.", bundleName.c_str(), status);
560 }
561 return status;
562 }
563 } // namespace UDMF
564 } // namespace OHOS