1 /*
2 * Copyright (c) 2020 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 "ability_mgr_feature.h"
17
18 #include "ability_callback_utils.h"
19 #include "ability_connect_trans_param.h"
20 #include "ability_errors.h"
21 #include "ability_info.h"
22 #include "ability_message_id.h"
23 #include "ability_mgr_handler.h"
24 #include "ability_service_interface.h"
25 #include "adapter.h"
26 #include "ohos_init.h"
27 #include "iproxy_client.h"
28 #include "rpc_errno.h"
29 #include "samgr_lite.h"
30 #include "securec.h"
31 #include "util/abilityms_helper.h"
32 #include "utils.h"
33 #include "want_utils.h"
34
35 namespace OHOS {
36 SvcIdentity AbilityMgrFeature::svc_ = {0};
37 IDmsListener* AbilityMgrFeature::myCallback_ = nullptr;
38
39 AbilityMgrFeatureImpl g_amsImpl = {
40 SERVER_IPROXY_IMPL_BEGIN,
41 .Invoke = AbilityMgrFeature::Invoke,
42 .StartAbility = AbilityMgrFeature::StartAbility,
43 .TerminateAbility = AbilityMgrFeature::TerminateAbility,
44 .ConnectAbility = AbilityMgrFeature::ConnectAbility,
45 .DisconnectAbility = AbilityMgrFeature::DisconnectAbility,
46 .StopAbility = AbilityMgrFeature::StopAbility,
47 IPROXY_END
48 };
49
50 InvokeFunc AbilityMgrFeature::invokeFuncList[INNER_BEGIN] {
51 AbilityMgrFeature::StartAbilityInvoke,
52 AbilityMgrFeature::TerminateAbilityInvoke,
53 AbilityMgrFeature::AttachBundleInvoke,
54 AbilityMgrFeature::ConnectAbilityInvoke,
55 AbilityMgrFeature::ConnectAbilityDoneInvoke,
56 AbilityMgrFeature::DisconnectAbilityInvoke,
57 AbilityMgrFeature::DisconnectAbilityDoneInvoke,
58 AbilityMgrFeature::AbilityTransactionDoneInvoke,
59 AbilityMgrFeature::StopAbilityInvoke,
60 AbilityMgrFeature::StartAbilityWithCbInvoke,
61 };
62
Init()63 static void Init()
64 {
65 SamgrLite *samgrLite = SAMGR_GetInstance();
66 CHECK_NULLPTR_RETURN(samgrLite, "AbilityMgrFeature", "get samgr error");
67 BOOL result = samgrLite->RegisterFeature(AMS_SERVICE, AbilityMgrFeature::GetInstance());
68 if (result == FALSE) {
69 PRINTE("AbilityMgrFeature", "ams register feature failure");
70 return;
71 }
72 g_amsImpl.ams = AbilityMgrFeature::GetInstance();
73 auto publicApi = GET_IUNKNOWN(g_amsImpl);
74 CHECK_NULLPTR_RETURN(publicApi, "AbilityMgrFeatureLite", "publicApi is nullptr");
75 BOOL apiResult = samgrLite->RegisterFeatureApi(AMS_SERVICE, AMS_FEATURE, publicApi);
76 PRINTI("AbilityMgrFeature", "ams feature init %{public}s", apiResult ? "success" : "failure");
77 }
78 SYSEX_FEATURE_INIT(Init);
79
AbilityMgrFeature()80 AbilityMgrFeature::AbilityMgrFeature() : Feature(), identity_()
81 {
82 this->Feature::GetName = AbilityMgrFeature::GetFeatureName;
83 this->Feature::OnInitialize = AbilityMgrFeature::OnFeatureInitialize;
84 this->Feature::OnStop = AbilityMgrFeature::OnFeatureStop;
85 this->Feature::OnMessage = AbilityMgrFeature::OnFeatureMessage;
86 }
87
Invoke(IServerProxy * iProxy,int funcId,void * origin,IpcIo * req,IpcIo * reply)88 int32 AbilityMgrFeature::Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply)
89 {
90 PRINTI("AbilityMgrFeature", "ams invoke called");
91 if (req == nullptr) {
92 return EC_INVALID;
93 }
94 if (funcId >= START_ABILITY && funcId < INNER_BEGIN) {
95 return invokeFuncList[funcId](origin, req);
96 }
97 return COMMAND_ERROR;
98 }
99
GetFeatureName(Feature * feature)100 const char *AbilityMgrFeature::GetFeatureName(Feature *feature)
101 {
102 (void) feature;
103 return AMS_FEATURE;
104 }
105
OnFeatureInitialize(Feature * feature,Service * parent,Identity identity)106 void AbilityMgrFeature::OnFeatureInitialize(Feature *feature, Service *parent, Identity identity)
107 {
108 CHECK_NULLPTR_RETURN(feature, "AbilityMgrFeature", "initialize fail");
109 (static_cast<AbilityMgrFeature *>(feature))->identity_ = identity;
110 AbilityMgrHandler::GetInstance().Init();
111 }
112
OnFeatureStop(Feature * feature,Identity identity)113 void AbilityMgrFeature::OnFeatureStop(Feature *feature, Identity identity)
114 {
115 (void) feature;
116 (void) identity;
117 AdapterFree(myCallback_);
118 }
119
OnFeatureMessage(Feature * feature,Request * request)120 BOOL AbilityMgrFeature::OnFeatureMessage(Feature *feature, Request *request)
121 {
122 if (feature == nullptr || request == nullptr) {
123 return FALSE;
124 }
125
126 AbilityMgrHandler::GetInstance().ServiceMsgProcess(*request);
127 return TRUE;
128 }
129
OnRequestCallback(const void * data,int32_t ret)130 void AbilityMgrFeature::OnRequestCallback(const void *data, int32_t ret)
131 {
132 IpcIo io;
133 char ipcData[MAX_IO_SIZE];
134 IpcIo reply;
135 IpcIoInit(&io, ipcData, MAX_IO_SIZE, 0);
136 WriteInt32(&io, static_cast<int32_t>(ret));
137 MessageOption option;
138 MessageOptionInit(&option);
139 option.flags = TF_OP_ASYNC;
140 int32_t transRet = SendRequest(svc_, START_ABILITY_CALLBACK, &io, &reply, option, NULL);
141 if (transRet != ERR_NONE) {
142 HILOG_ERROR(HILOG_MODULE_APP, "AbilityMgrFeature InnerSelfTransact failed %{public}d\n", ret);
143 }
144 ReleaseSvc(svc_);
145 }
146
StartAbilityInvoke(const void * origin,IpcIo * req)147 int32 AbilityMgrFeature::StartAbilityInvoke(const void *origin, IpcIo *req)
148 {
149 pid_t uid = GetCallingUid();
150 if (uid < 0) {
151 PRINTE("AbilityMgrFeature", "invalid uid argument");
152 return EC_INVALID;
153 }
154 Want want = { nullptr, nullptr, nullptr, 0};
155 if (!DeserializeWant(&want, req)) {
156 return EC_FAILURE;
157 }
158 if (want.element == nullptr) {
159 PRINTE("AbilityMgrFeature", "invalid argument");
160 return EC_INVALID;
161 }
162 const char *deviceId = want.element->deviceId;
163
164 int32 retVal;
165 if (deviceId != nullptr && *deviceId != '\0') {
166 retVal = StartRemoteAbilityInner(&want, deviceId, uid, nullptr);
167 } else {
168 retVal = StartAbilityInner(&want, uid);
169 }
170 ClearWant(&want);
171 return retVal;
172 }
173
StartAbilityWithCbInvoke(const void * origin,IpcIo * req)174 int32 AbilityMgrFeature::StartAbilityWithCbInvoke(const void *origin, IpcIo *req)
175 {
176 pid_t uid = GetCallingUid();
177 if (uid < 0) {
178 PRINTE("AbilityMgrFeature", "invalid uid argument");
179 return EC_INVALID;
180 }
181 SvcIdentity svc;
182 bool ret = ReadRemoteObject(req, &svc);
183 if (!ret) {
184 svc_ = {0};
185 return EC_INVALID;
186 }
187 svc_ = svc;
188 Want want = { nullptr, nullptr, nullptr, 0};
189 if (!DeserializeWant(&want, req)) {
190 return EC_FAILURE;
191 }
192 if (want.element == nullptr) {
193 PRINTE("AbilityMgrFeature", "invalid argument");
194 return EC_INVALID;
195 }
196 const char *deviceId = want.element->deviceId;
197
198 int32 retVal = EC_FAILURE;
199 if (deviceId != nullptr && *deviceId != '\0') {
200 retVal = StartRemoteAbilityInner(&want, deviceId, uid, OnRequestCallback);
201 }
202 ClearWant(&want);
203 return retVal;
204 }
205
StartAbility(const Want * want)206 int32 AbilityMgrFeature::StartAbility(const Want *want)
207 {
208 return StartAbilityInner(want, -1);
209 }
210
StartRemoteAbilityInner(const Want * want,const char * deviceId,pid_t uid,OnRequestCallbackFunc callback)211 int32 AbilityMgrFeature::StartRemoteAbilityInner(const Want *want, const char *deviceId,
212 pid_t uid, OnRequestCallbackFunc callback)
213 {
214 IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(DISTRIBUTED_SCHEDULE_SERVICE, DMSLITE_FEATURE);
215 DmsProxy *dmsInterface = NULL;
216 if (iUnknown == NULL) {
217 return EC_INVALID;
218 }
219 int32 retVal = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void**) &dmsInterface);
220 if (retVal != EC_SUCCESS) {
221 return EC_INVALID;
222 }
223 CallerInfo callerInfo = {
224 .uid = uid
225 };
226
227 if (callback != nullptr) {
228 if (myCallback_ == nullptr) {
229 myCallback_ = new IDmsListener();
230 }
231 myCallback_ -> OnResultCallback = callback;
232 retVal = dmsInterface->StartRemoteAbility((Want *)want, &callerInfo, myCallback_);
233 } else {
234 retVal = dmsInterface->StartRemoteAbility((Want *)want, &callerInfo, NULL);
235 }
236 return retVal;
237 }
238
StartAbilityInner(const Want * want,pid_t callingUid)239 int32 AbilityMgrFeature::StartAbilityInner(const Want *want, pid_t callingUid)
240 {
241 if (want == nullptr || want->element == nullptr) {
242 PRINTE("AbilityMgrFeature", "invalid argument");
243 return EC_INVALID;
244 }
245 Want *data = new Want();
246 if (memset_s(data, sizeof(Want), 0, sizeof(Want)) != EOK) {
247 PRINTE("AbilityMgrFeature", "memory alloc error");
248 delete data;
249 return EC_NOMEMORY;
250 }
251 SetWantElement(data, *(want->element));
252 SetWantData(data, want->data, want->dataLength);
253 if (want->sid != nullptr) {
254 SetWantSvcIdentity(data, *(want->sid));
255 }
256 Request request = {
257 .msgId = AMS_START_ABILITY,
258 .len = 0,
259 .data = reinterpret_cast<void *>(data),
260 .msgValue = static_cast<uint32>(callingUid),
261 };
262 int32 propRet = SAMGR_SendRequest(&(GetInstance()->identity_), &request, nullptr);
263 if (propRet != EC_SUCCESS) {
264 PRINTE("AbilityMgrFeature", "send request failure");
265 ClearWant(data);
266 delete data;
267 return EC_COMMU;
268 }
269 return EC_SUCCESS;
270 }
271
TerminateAbilityInvoke(const void * origin,IpcIo * req)272 int32 AbilityMgrFeature::TerminateAbilityInvoke(const void *origin, IpcIo *req)
273 {
274 uint64_t token = 0;
275 ReadUint64(req, &token);
276 return TerminateAbility(token);
277 }
278
TerminateAbility(uint64_t token)279 int32 AbilityMgrFeature::TerminateAbility(uint64_t token)
280 {
281 uint64_t *terminateToken = new uint64_t;
282 *terminateToken = token;
283 Request request = {
284 .msgId = AMS_TERMINATE_ABILITY,
285 .len = 0,
286 .data = reinterpret_cast<void *>(terminateToken),
287 };
288 int32 propRet = SAMGR_SendRequest(&(GetInstance()->identity_), &request, nullptr);
289 if (propRet != EC_SUCCESS) {
290 PRINTE("AbilityMgrFeature", "send request failure");
291 delete terminateToken;
292 return EC_COMMU;
293 }
294 return EC_SUCCESS;
295 }
296
AbilityTransactionDoneInvoke(const void * origin,IpcIo * req)297 int32 AbilityMgrFeature::AbilityTransactionDoneInvoke(const void *origin, IpcIo *req)
298 {
299 uint64_t token = 0;
300 ReadUint64(req, &token);
301 int32_t ret = 0;
302 ReadInt32(req, &ret);
303 int32 state = static_cast<int32>(ret);
304
305 TransactionState *transactionState = new TransactionState();
306 transactionState->token = token;
307 transactionState->state = state;
308 Request request = {
309 .msgId = AMS_TRANSACTION_DONE,
310 .len = 0,
311 .data = reinterpret_cast<void *>(transactionState),
312 };
313 int32 propRet = SAMGR_SendRequest(&(GetInstance()->identity_), &request, nullptr);
314 if (propRet != EC_SUCCESS) {
315 PRINTE("AbilityMgrFeature", "send request failure");
316 delete transactionState;
317 return EC_COMMU;
318 }
319 return EC_SUCCESS;
320 }
321
AttachBundleInvoke(const void * origin,IpcIo * req)322 int32 AbilityMgrFeature::AttachBundleInvoke(const void *origin, IpcIo *req)
323 {
324 uint64_t token = 0;
325 ReadUint64(req, &token);
326 SvcIdentity svc;
327 bool ret = ReadRemoteObject(req, &svc);
328 if (!ret) {
329 return EC_INVALID;
330 }
331
332 #ifdef __LINUX__
333 uint64_t readData = 0;
334 ReadUint64(req, &readData);
335 pid_t callingPid = static_cast<pid_t>(readData);
336 #else
337 pid_t callingPid = GetCallingPid();
338 #endif
339 if (callingPid < 0) {
340 PRINTE("AbilityMgrFeature", "invalid pid argument");
341 return EC_INVALID;
342 }
343
344 auto client = new AbilityThreadClient(token, callingPid, svc, &AbilityMgrFeature::AppDeathNotify);
345 Request request = {
346 .msgId = AMS_ATTACH_BUNDLE,
347 .len = 0,
348 .data = reinterpret_cast<void *>(client),
349 };
350 int32 propRet = SAMGR_SendRequest(&(GetInstance()->identity_), &request, nullptr);
351 if (propRet != EC_SUCCESS) {
352 PRINTE("AbilityMgrFeature", "send request failure");
353 delete client;
354 return EC_COMMU;
355 }
356 return EC_SUCCESS;
357 }
358
ConnectAbilityInvoke(const void * origin,IpcIo * req)359 int32 AbilityMgrFeature::ConnectAbilityInvoke(const void *origin, IpcIo *req)
360 {
361 pid_t uid = GetCallingUid();
362 if (uid < 0) {
363 PRINTE("AbilityMgrFeature", "invalid uid argument");
364 return EC_INVALID;
365 }
366 uint64_t token = 0;
367 ReadUint64(req, &token);
368 SvcIdentity svc;
369 bool ret = ReadRemoteObject(req, &svc);
370 if (!ret) {
371 return EC_INVALID;
372 }
373 Want want = { nullptr, nullptr, nullptr, 0 };
374 if (!DeserializeWant(&want, req)) {
375 return EC_FAILURE;
376 }
377 int32 retVal = ConnectAbilityInner(&want, &svc, token, uid);
378 ClearWant(&want);
379 return retVal;
380 }
381
ConnectAbility(const Want * want,SvcIdentity * svc,uint64_t token)382 int32 AbilityMgrFeature::ConnectAbility(const Want *want, SvcIdentity *svc, uint64_t token)
383 {
384 return ConnectAbilityInner(want, svc, token, -1);
385 }
386
ConnectAbilityInner(const Want * want,SvcIdentity * svc,uint64_t token,pid_t callingUid)387 int32 AbilityMgrFeature::ConnectAbilityInner(const Want *want, SvcIdentity *svc, uint64_t token, pid_t callingUid)
388 {
389 if (want == nullptr || want->element == nullptr || svc == nullptr) {
390 return EC_INVALID;
391 }
392 Want *data = new Want();
393 if (memset_s(data, sizeof(Want), 0, sizeof(Want)) != EOK) {
394 delete data;
395 PRINTE("AbilityMgrFeature", "memory alloc error");
396 return EC_NOMEMORY;
397 }
398 SetWantElement(data, *(want->element));
399 SetWantData(data, want->data, want->dataLength);
400 if (want->sid != nullptr) {
401 SetWantSvcIdentity(data, *(want->sid));
402 }
403 auto transParam = new AbilityConnectTransParam(data, *svc, token);
404 transParam->SetCallingUid(callingUid);
405 Request request = {
406 .msgId = AMS_CONNECT_ABILITY,
407 .len = 0,
408 .data = reinterpret_cast<void *>(transParam),
409 };
410 int32 propRet = SAMGR_SendRequest(&(GetInstance()->identity_), &request, nullptr);
411 if (propRet != EC_SUCCESS) {
412 PRINTE("AbilityMgrFeature", "connect ability send request failure");
413 delete transParam;
414 return EC_COMMU;
415 }
416 return EC_SUCCESS;
417 }
418
DisconnectAbilityInvoke(const void * origin,IpcIo * req)419 int32 AbilityMgrFeature::DisconnectAbilityInvoke(const void *origin, IpcIo *req)
420 {
421 uint64_t token = 0;
422 ReadUint64(req, &token);
423 SvcIdentity svc;
424 bool ret = ReadRemoteObject(req, &svc);
425 if (!ret) {
426 return EC_INVALID;
427 }
428 return DisconnectAbility(&svc, token);
429 }
430
DisconnectAbility(SvcIdentity * svc,uint64_t token)431 int32 AbilityMgrFeature::DisconnectAbility(SvcIdentity *svc, uint64_t token)
432 {
433 if (svc == nullptr) {
434 return EC_INVALID;
435 }
436 auto transParam = new AbilityConnectTransParam(nullptr, *svc, token);
437 Request request = {
438 .msgId = AMS_DISCONNECT_ABILITY,
439 .len = 0,
440 .data = reinterpret_cast<void *>(transParam),
441 };
442 int32 propRet = SAMGR_SendRequest(&(GetInstance()->identity_), &request, nullptr);
443 if (propRet != EC_SUCCESS) {
444 PRINTE("AbilityMgrFeature", "disconnect ability send request failure");
445 delete transParam;
446 return EC_COMMU;
447 }
448 return EC_SUCCESS;
449 }
450
ConnectAbilityDoneInvoke(const void * origin,IpcIo * req)451 int32 AbilityMgrFeature::ConnectAbilityDoneInvoke(const void *origin, IpcIo *req)
452 {
453 uint64_t token = 0;
454 ReadUint64(req, &token);
455 SvcIdentity svc;
456 bool ret = ReadRemoteObject(req, &svc);
457 if (!ret) {
458 return EC_INVALID;
459 }
460
461 auto transParam = new AbilityConnectTransParam(nullptr, svc, token);
462 Request request = {
463 .msgId = AMS_CONNECT_ABILITY_DONE,
464 .len = 0,
465 .data = reinterpret_cast<void *>(transParam),
466 };
467 int32 propRet = SAMGR_SendRequest(&(GetInstance()->identity_), &request, nullptr);
468 if (propRet != EC_SUCCESS) {
469 PRINTE("AbilityMgrFeature", "connect ability done send request failure");
470 delete transParam;
471 return EC_COMMU;
472 }
473 return EC_SUCCESS;
474 }
475
DisconnectAbilityDoneInvoke(const void * origin,IpcIo * req)476 int32 AbilityMgrFeature::DisconnectAbilityDoneInvoke(const void *origin, IpcIo *req)
477 {
478 uint64_t *disconnectToken = new uint64_t;
479 uint64_t ret = 0;
480 ReadUint64(req, &ret);
481 *disconnectToken = ret;
482 Request request = {
483 .msgId = AMS_DISCONNECT_ABILITY_DONE,
484 .len = 0,
485 .data = reinterpret_cast<void *>(disconnectToken),
486 };
487 int32 propRet = SAMGR_SendRequest(&(GetInstance()->identity_), &request, nullptr);
488 if (propRet != EC_SUCCESS) {
489 PRINTE("AbilityMgrFeature", "disconnect ability done send request failure");
490 delete disconnectToken;
491 return EC_COMMU;
492 }
493 return EC_SUCCESS;
494 }
495
StopAbilityInvoke(const void * origin,IpcIo * req)496 int32 AbilityMgrFeature::StopAbilityInvoke(const void *origin, IpcIo *req)
497 {
498 pid_t uid = GetCallingUid();
499 if (uid < 0) {
500 PRINTE("AbilityMgrFeature", "invalid uid argument");
501 return EC_INVALID;
502 }
503 Want want = { nullptr, nullptr, nullptr, 0 };
504 if (!DeserializeWant(&want, req)) {
505 return EC_FAILURE;
506 }
507 int retVal = StopAbilityInner(&want, uid);
508 ClearWant(&want);
509 return retVal;
510 }
511
StopAbility(const Want * want)512 int32 AbilityMgrFeature::StopAbility(const Want *want)
513 {
514 return StopAbilityInner(want, -1);
515 }
516
StopAbilityInner(const Want * want,pid_t callingUid)517 int32 AbilityMgrFeature::StopAbilityInner(const Want *want, pid_t callingUid)
518 {
519 if (want == nullptr || want->element == nullptr) {
520 PRINTE("AbilityMgrFeature", "invalid argument");
521 return EC_INVALID;
522 }
523 Want *data = new Want();
524 if (memset_s(data, sizeof(Want), 0, sizeof(Want)) != EOK) {
525 PRINTE("AbilityMgrFeature", "memory alloc error");
526 delete data;
527 return EC_NOMEMORY;
528 }
529 SetWantElement(data, *(want->element));
530 SetWantData(data, want->data, want->dataLength);
531 if (want->sid != nullptr) {
532 SetWantSvcIdentity(data, *(want->sid));
533 }
534 Request request = {
535 .msgId = AMS_TERMINATE_SERVICE,
536 .len = 0,
537 .data = reinterpret_cast<void *>(data),
538 .msgValue = static_cast<uint32>(callingUid),
539 };
540 int32 propRet = SAMGR_SendRequest(&(GetInstance()->identity_), &request, nullptr);
541 if (propRet != EC_SUCCESS) {
542 PRINTE("AbilityMgrFeature", "send request failure");
543 ClearWant(data);
544 delete data;
545 return EC_COMMU;
546 }
547 return EC_SUCCESS;
548 }
549
RestartApp(const char * bundleName)550 int32 AbilityMgrFeature::RestartApp(const char *bundleName)
551 {
552 if (!AbilityMsHelper::IsLegalBundleName(bundleName)) {
553 return EC_INVALID;
554 }
555 char *name = Utils::Strdup(bundleName);
556 if (name == nullptr) {
557 return EC_NOMEMORY;
558 }
559 Request request = {
560 .msgId = AMS_RESTART_APP,
561 .len = 0,
562 .data = reinterpret_cast<void *>(name),
563 };
564 int32 propRet = SAMGR_SendRequest(&(GetInstance()->identity_), &request, nullptr);
565 if (propRet != EC_SUCCESS) {
566 PRINTE("AbilityMgrFeature", "send request failure");
567 AdapterFree(name);
568 return EC_COMMU;
569 }
570 return EC_SUCCESS;
571 }
572
AppDeathNotify(void * args)573 void AbilityMgrFeature::AppDeathNotify(void *args)
574 {
575 AppInfo *appInfo = reinterpret_cast<AppInfo *>(args);
576 if (appInfo == nullptr) {
577 return;
578 }
579 ReleaseSvc(appInfo->svcIdentity);
580 if (!AbilityMsHelper::IsLegalBundleName(appInfo->bundleName)) {
581 AdapterFree(appInfo->bundleName);
582 delete appInfo;
583 return;
584 }
585 PRINTE("AbilityMgrFeature", "%s AppDeathNotify called", appInfo->bundleName);
586 int32 ret = RestartApp(appInfo->bundleName);
587 if (ret != EC_SUCCESS) {
588 PRINTE("AbilityMgrFeature", "restart app failure");
589 }
590 AdapterFree(appInfo->bundleName);
591 delete appInfo;
592 }
593 } // namespace OHOS
594