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 "client/app_spawn_client.h"
17
18 #include "appspawn_service.h"
19 #include "cJSON.h"
20 #include "ohos_errno.h"
21 #include "ipc_skeleton.h"
22 #include "samgr_lite.h"
23 #include "securec.h"
24 #include "util/abilityms_log.h"
25
26 namespace OHOS {
27 const unsigned long SLEEP_TIMES = 200000;
28 const int RETRY_TIMES_MAX = 30;
29
Notify(IOwner owner,int code,IpcIo * reply)30 static int Notify(IOwner owner, int code, IpcIo *reply)
31 {
32 if (reply == nullptr || owner == nullptr) {
33 return EC_INVALID;
34 }
35 int64_t *result = reinterpret_cast<int64_t *>(owner);
36 ReadInt64(reply, result);
37 return EC_SUCCESS;
38 }
39
Initialize()40 AbilityMsStatus AppSpawnClient::Initialize()
41 {
42 while (spawnClient_ == nullptr) {
43 IUnknown *iUnknown = SAMGR_GetInstance()->GetDefaultFeatureApi(APPSPAWN_SERVICE_NAME);
44 if (iUnknown == nullptr) {
45 PRINTW("AppSpawnClient", "get default feature api fail, again try");
46 usleep(SLEEP_TIMES); // sleep 200ms
47 continue;
48 }
49 int result = iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)(&spawnClient_));
50 if (result != EC_SUCCESS || spawnClient_ == nullptr) {
51 PRINTW("AppSpawnClient", "get app spawn client fail");
52 usleep(SLEEP_TIMES); // sleep 200ms
53 continue;
54 }
55 }
56 return AbilityMsStatus::Ok();
57 }
58
CallingInnerSpawnProcess(char * spawnMessage,AppRecord & appRecord)59 AbilityMsStatus AppSpawnClient::CallingInnerSpawnProcess(char *spawnMessage, AppRecord &appRecord)
60 {
61 if (spawnMessage == nullptr) {
62 return AbilityMsStatus::ProcessStatus("CallingInnerSpawnProcess spawnMessage is nullptr");
63 }
64 if (spawnClient_ == nullptr) {
65 AbilityMsStatus status = Initialize();
66 if (!status.IsOk()) {
67 cJSON_free(spawnMessage);
68 return AbilityMsStatus::ProcessStatus("CallingInnerSpawnProcess Initialize unsuccessfully");
69 }
70 }
71
72 IpcIo request;
73 char data[MAX_IO_SIZE];
74 IpcIoInit(&request, data, MAX_IO_SIZE, 0);
75 WriteString(&request, spawnMessage);
76 pid_t pid = -1;
77 int result = spawnClient_->Invoke(spawnClient_, ID_CALL_CREATE_SERVICE, &request, &pid, Notify);
78 int retry = 0;
79 while (result != EC_SUCCESS && retry < RETRY_TIMES_MAX) {
80 ++retry;
81 PRINTI("AppManager", "invoke fail: %{public}d, retry times: %{public}d", result, retry);
82 usleep(SLEEP_TIMES); // sleep 200ms if invoke fail.
83 result = spawnClient_->Invoke(spawnClient_, ID_CALL_CREATE_SERVICE, &request, &pid, Notify);
84 }
85 if (result != EC_SUCCESS) {
86 return AbilityMsStatus::ProcessStatus("spawn process fail");
87 }
88 appRecord.SetPid(pid);
89 return AbilityMsStatus::Ok();
90 }
91
SpawnProcess(AppRecord & appRecord)92 AbilityMsStatus AppSpawnClient::SpawnProcess(AppRecord &appRecord)
93 {
94 char *innerBundleName = appRecord.GetBundleInfo().bundleName;
95 if (innerBundleName == nullptr) {
96 return AbilityMsStatus::ProcessStatus("invalid argument");
97 }
98
99 cJSON *root = cJSON_CreateObject();
100 if (root == nullptr) {
101 return AbilityMsStatus::ProcessStatus("SpawnProcess create fail");
102 }
103 cJSON_AddStringToObject(root, "bundleName", innerBundleName);
104 std::string identityId = std::to_string(appRecord.GetIdentityId());
105 cJSON_AddStringToObject(root, "identityID", identityId.c_str());
106 cJSON_AddNumberToObject(root, "uID", appRecord.GetBundleInfo().uid);
107 cJSON_AddNumberToObject(root, "gID", appRecord.GetBundleInfo().gid);
108
109 cJSON *caps = cJSON_AddArrayToObject(root, "capability");
110 if (caps == nullptr) {
111 cJSON_Delete(root);
112 return AbilityMsStatus::ProcessStatus("SpawnProcess create array unsuccessfully");
113 }
114
115 uint32_t *capabilities = nullptr;
116 uint32_t capNums = 0;
117 AbilityMsStatus status = appRecord.QueryAppCapability(innerBundleName, &capabilities, &capNums);
118 if (!status.IsOk()) {
119 cJSON_Delete(root);
120 return AbilityMsStatus::ProcessStatus("SpawnProcess QueryAppCapability unsuccessfully");
121 }
122 if ((capabilities != nullptr) && (capNums != 0)) {
123 for (int32_t i = 0; i < capNums; ++i) {
124 cJSON *item = cJSON_CreateNumber(capabilities[i]);
125 if ((item == nullptr) || !cJSON_AddItemToArray(caps, item)) {
126 free(capabilities);
127 capabilities = nullptr;
128 cJSON_Delete(item);
129 cJSON_Delete(root);
130 return AbilityMsStatus::ProcessStatus("SpawnProcess add item to array unsuccessfully");
131 }
132 }
133 free(capabilities);
134 capabilities = nullptr;
135 }
136 char *spawnMessage = cJSON_PrintUnformatted(root);
137 cJSON_Delete(root);
138
139 return CallingInnerSpawnProcess(spawnMessage, appRecord);
140 }
141 } // namespace OHOS
142