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 "liteipc_adapter.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 *result = IpcIoPopInt64(reply);
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
InnerFreeDataBuff(void * ptr)59 static void InnerFreeDataBuff(void *ptr)
60 {
61 if (ptr != nullptr) {
62 cJSON_free(ptr);
63 }
64 }
65
CallingInnerSpawnProcess(char * spawnMessage,AppRecord & appRecord)66 AbilityMsStatus AppSpawnClient::CallingInnerSpawnProcess(char *spawnMessage, AppRecord &appRecord)
67 {
68 if (spawnMessage == nullptr) {
69 return AbilityMsStatus::ProcessStatus("CallingInnerSpawnProcess spawnMessage is nullptr");
70 }
71 if (spawnClient_ == nullptr) {
72 AbilityMsStatus status = Initialize();
73 if (!status.IsOk()) {
74 cJSON_free(spawnMessage);
75 return AbilityMsStatus::ProcessStatus("CallingInnerSpawnProcess Initialize unsuccessfully");
76 }
77 }
78
79 IpcIo request;
80 char data[IPC_IO_DATA_MAX];
81 #ifdef __LINUX__
82 IpcIoInit(&request, data, IPC_IO_DATA_MAX, 0);
83 IpcIoPushString(&request, spawnMessage);
84 #else
85 IpcIoInit(&request, data, IPC_IO_DATA_MAX, 1);
86 BuffPtr dataBuff = {
87 .buffSz = strlen(spawnMessage) + 1, // include \0
88 .buff = spawnMessage,
89 };
90 IpcIoPushDataBuffWithFree(&request, &dataBuff, InnerFreeDataBuff);
91 #endif
92 pid_t pid = -1;
93 int result = spawnClient_->Invoke(spawnClient_, ID_CALL_CREATE_SERVICE, &request, &pid, Notify);
94 int retry = 0;
95 while (result != EC_SUCCESS && retry < RETRY_TIMES_MAX) {
96 ++retry;
97 PRINTI("AppManager", "invoke fail: %{public}d, retry times: %{public}d", result, retry);
98 usleep(SLEEP_TIMES); // sleep 200ms if invoke fail.
99 result = spawnClient_->Invoke(spawnClient_, ID_CALL_CREATE_SERVICE, &request, &pid, Notify);
100 }
101 if (result != EC_SUCCESS) {
102 return AbilityMsStatus::ProcessStatus("spawn process fail");
103 }
104 appRecord.SetPid(pid);
105 return AbilityMsStatus::Ok();
106 }
107
SpawnProcess(AppRecord & appRecord)108 AbilityMsStatus AppSpawnClient::SpawnProcess(AppRecord &appRecord)
109 {
110 char *innerBundleName = appRecord.GetBundleInfo().bundleName;
111 if (innerBundleName == nullptr) {
112 return AbilityMsStatus::ProcessStatus("invalid argument");
113 }
114
115 cJSON *root = cJSON_CreateObject();
116 if (root == nullptr) {
117 return AbilityMsStatus::ProcessStatus("SpawnProcess create fail");
118 }
119 cJSON_AddStringToObject(root, "bundleName", innerBundleName);
120 std::string identityId = std::to_string(appRecord.GetIdentityId());
121 cJSON_AddStringToObject(root, "identityID", identityId.c_str());
122 cJSON_AddNumberToObject(root, "uID", appRecord.GetBundleInfo().uid);
123 cJSON_AddNumberToObject(root, "gID", appRecord.GetBundleInfo().gid);
124
125 cJSON *caps = cJSON_AddArrayToObject(root, "capability");
126 if (caps == nullptr) {
127 cJSON_Delete(root);
128 return AbilityMsStatus::ProcessStatus("SpawnProcess create array unsuccessfully");
129 }
130
131 uint32_t *capabilities = nullptr;
132 uint32_t capNums = 0;
133 AbilityMsStatus status = appRecord.QueryAppCapability(innerBundleName, &capabilities, &capNums);
134 if (!status.IsOk()) {
135 cJSON_Delete(root);
136 return AbilityMsStatus::ProcessStatus("SpawnProcess QueryAppCapability unsuccessfully");
137 }
138 if ((capabilities != nullptr) && (capNums != 0)) {
139 for (int32_t i = 0; i < capNums; ++i) {
140 cJSON *item = cJSON_CreateNumber(capabilities[i]);
141 if ((item == nullptr) || !cJSON_AddItemToArray(caps, item)) {
142 free(capabilities);
143 capabilities = nullptr;
144 cJSON_Delete(item);
145 cJSON_Delete(root);
146 return AbilityMsStatus::ProcessStatus("SpawnProcess add item to array unsuccessfully");
147 }
148 }
149 free(capabilities);
150 capabilities = nullptr;
151 }
152 char *spawnMessage = cJSON_PrintUnformatted(root);
153 cJSON_Delete(root);
154
155 return CallingInnerSpawnProcess(spawnMessage, appRecord);
156 }
157 } // namespace OHOS
158