1 /*
2 * Copyright (c) 2023 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 "app_native_spawn_manager.h"
17
18 #include <nlohmann/json.hpp>
19 #include <sys/epoll.h>
20
21 #include "ability_manager_errors.h"
22 #include "appspawn.h"
23 #include "c/executor_task.h"
24 #include "ffrt.h"
25 #include "ffrt_inner.h"
26 #include "hilog_tag_wrapper.h"
27 #include "ipc_skeleton.h"
28 #include "syspara/parameter.h"
29
30 namespace OHOS {
31 namespace AppExecFwk {
32
33 namespace {
34 //listen fd use
35 constexpr int32_t PIPE_MSG_READ_BUFFER = 1024;
36 constexpr const char* NATIVESPAWN_STARTED = "startup.service.ctl.nativespawn.pid";
37 }
38
~AppNativeSpawnManager()39 AppNativeSpawnManager::~AppNativeSpawnManager() {}
40
AppNativeSpawnManager()41 AppNativeSpawnManager::AppNativeSpawnManager() {}
42
GetInstance()43 AppNativeSpawnManager &AppNativeSpawnManager::GetInstance()
44 {
45 static AppNativeSpawnManager manager;
46 return manager;
47 }
48
RegisterNativeChildExitNotify(const sptr<INativeChildNotify> & callback)49 int32_t AppNativeSpawnManager::RegisterNativeChildExitNotify(const sptr<INativeChildNotify> &callback)
50 {
51 if (callback == nullptr) {
52 TAG_LOGE(AAFwkTag::APPMGR, "register null callback");
53 return ERR_INVALID_VALUE;
54 }
55 int32_t callingPid = IPCSkeleton::GetCallingPid();
56 auto appRecord = appRunningManager_->GetAppRunningRecordByPid(callingPid);
57 if (!appRecord) {
58 TAG_LOGE(AAFwkTag::APPMGR, "no appRecord, parentPid:%{public}d", callingPid);
59 return OHOS::AAFwk::ERR_CALLER_NOT_EXISTS;
60 }
61 std::lock_guard lock(nativeChildCallbackLock_);
62 if (nativeChildCallbackMap_.find(callingPid) != nativeChildCallbackMap_.end()) {
63 TAG_LOGE(AAFwkTag::APPMGR, "register native child exit:%{public}d fail", callingPid);
64 return OHOS::AAFwk::ERR_INVALID_CALLER;
65 }
66 nativeChildCallbackMap_[callingPid] = callback;
67 TAG_LOGI(AAFwkTag::APPMGR, "register native child exit:%{public}d success", callingPid);
68 return ERR_OK;
69 }
70
UnregisterNativeChildExitNotify(const sptr<INativeChildNotify> & callback)71 int32_t AppNativeSpawnManager::UnregisterNativeChildExitNotify(const sptr<INativeChildNotify> &callback)
72 {
73 if (callback == nullptr) {
74 TAG_LOGE(AAFwkTag::APPMGR, "unregister null callback");
75 return ERR_INVALID_VALUE;
76 }
77 int32_t callingPid = IPCSkeleton::GetCallingPid();
78 std::lock_guard lock(nativeChildCallbackLock_);
79 auto iter = nativeChildCallbackMap_.find(callingPid);
80 if (iter == nativeChildCallbackMap_.end()) {
81 TAG_LOGE(AAFwkTag::APPMGR, "unregister callback not exist:%{public}d", callingPid);
82 return OHOS::AAFwk::ERR_INVALID_CALLER;
83 }
84 if (iter->second == nullptr || iter->second->AsObject() != callback->AsObject()) {
85 TAG_LOGE(AAFwkTag::APPMGR, "unregister callback not same:%{public}d", callingPid);
86 return OHOS::AAFwk::ERR_INVALID_CALLER;
87 }
88
89 nativeChildCallbackMap_.erase(callingPid);
90 TAG_LOGI(AAFwkTag::APPMGR, "unregister native child exit:%{public}d success", callingPid);
91 return ERR_OK;
92 }
93
AppNativeSpawnStartCallback(const char * key,const char * value,void * context)94 static void AppNativeSpawnStartCallback(const char *key, const char *value, void *context)
95 {
96 int nrFd = AppNativeSpawnManager::GetInstance().GetNRfd();
97 int nwFd = AppNativeSpawnManager::GetInstance().GetNWfd();
98 TAG_LOGI(AAFwkTag::APPMGR, "nrFd is: %{public}d, nwFd is: %{public}d", nrFd, nwFd);
99 // send fd
100 int ret = NativeSpawnListenFdSet(nwFd);
101 if (ret != 0) {
102 TAG_LOGE(AAFwkTag::APPMGR, "send fd to native spawn failed, ret: %{public}d", ret);
103 close(nrFd);
104 close(nwFd);
105 return;
106 }
107 // set flag
108 ret = NativeSpawnListenCloseSet();
109 if (ret != 0) {
110 TAG_LOGI(AAFwkTag::APPMGR, "NativeSpawnListenCloseSet failed");
111 }
112 }
113
NotifyChildProcessExitTask(int32_t pid,int32_t signal,const std::string & bundleName)114 void AppNativeSpawnManager::NotifyChildProcessExitTask(int32_t pid, int32_t signal, const std::string &bundleName)
115 {
116 if (!appRunningManager_) {
117 TAG_LOGE(AAFwkTag::APPMGR, "get appRunningManager fail");
118 return;
119 }
120
121 int32_t parentPid = 0;
122 auto appRecord = appRunningManager_->GetAppRunningRecordByChildProcessPid(pid);
123 if (!appRecord) {
124 parentPid = GetChildRelation(pid);
125 if (parentPid <= 0) {
126 TAG_LOGE(AAFwkTag::APPMGR, "not find parent, childPid:%{public}d", pid);
127 return;
128 }
129 RemoveChildRelation(pid);
130 } else {
131 parentPid = appRecord->GetPid();
132 }
133
134 auto nativeChildCallbacks = GetNativeChildCallbackByPid(parentPid);
135 if (!nativeChildCallbacks) {
136 TAG_LOGW(AAFwkTag::APPMGR, "not found native child process callback");
137 return;
138 }
139 auto ret = nativeChildCallbacks->OnNativeChildExit(pid, signal);
140 if (ret != ERR_OK) {
141 TAG_LOGE(AAFwkTag::APPMGR, "OnNativeChildExit failed, pid: %{public}d", pid);
142 }
143 }
144
ProcessSignalData(void * token,uint32_t event)145 static void ProcessSignalData(void *token, uint32_t event)
146 {
147 int rFd = AppNativeSpawnManager::GetInstance().GetNRfd();
148 if (rFd <= 0) {
149 TAG_LOGE(AAFwkTag::APPMGR, "rFd is invalid, %{public}d", rFd);
150 return;
151 }
152
153 // read data from nativespawn
154 char buffer[PIPE_MSG_READ_BUFFER] = {0};
155 std::string readResult = "";
156 int count = read(rFd, buffer, PIPE_MSG_READ_BUFFER - 1);
157 if (count <= 0) {
158 TAG_LOGE(AAFwkTag::APPMGR, "read pipe failed");
159 return;
160 }
161
162 int32_t pid = -1;
163 int32_t signal = -1;
164 int32_t uid = 0;
165 std::string bundleName = "";
166 std::string bufferStr = buffer;
167 TAG_LOGD(AAFwkTag::APPMGR, "buffer read: %{public}s", bufferStr.c_str());
168 nlohmann::json jsonObject = nlohmann::json::parse(bufferStr, nullptr, false);
169 if (jsonObject.is_discarded()) {
170 TAG_LOGE(AAFwkTag::APPMGR, "parse json string failed");
171 return;
172 }
173 if (!jsonObject.contains("pid") || !jsonObject.contains("signal") || !jsonObject.contains("uid")
174 || !jsonObject.contains("bundleName")) {
175 TAG_LOGE(AAFwkTag::APPMGR, "info lost!");
176 return;
177 }
178 if (!jsonObject["pid"].is_number_integer() || !jsonObject["signal"].is_number_integer() ||
179 !jsonObject["uid"].is_number_integer() || !jsonObject["bundleName"].is_string()) {
180 TAG_LOGE(AAFwkTag::APPMGR, "info type err!");
181 return;
182 }
183
184 pid = jsonObject["pid"];
185 signal = jsonObject["signal"];
186 uid = jsonObject["uid"];
187 bundleName = jsonObject["bundleName"];
188 TAG_LOGI(AAFwkTag::APPMGR, "pid:%{public}d, signal:%{public}d, uid:%{public}d, bundleName:%{public}s",
189 pid, signal, uid, bundleName.c_str());
190 AppNativeSpawnManager::GetInstance().NotifyChildProcessExitTask(pid, signal, bundleName);
191 }
192
GetNativeChildCallbackByPid(int32_t pid)193 sptr<INativeChildNotify> AppNativeSpawnManager::GetNativeChildCallbackByPid(int32_t pid)
194 {
195 std::lock_guard lock(nativeChildCallbackLock_);
196 auto it = nativeChildCallbackMap_.find(pid);
197 return it != nativeChildCallbackMap_.end() ? it->second : nullptr;
198 }
199
RemoveNativeChildCallbackByPid(int32_t pid)200 void AppNativeSpawnManager::RemoveNativeChildCallbackByPid(int32_t pid)
201 {
202 TAG_LOGI(AAFwkTag::APPMGR, "remove native child callback, pid:%{public}d", pid);
203 std::lock_guard lock(nativeChildCallbackLock_);
204 nativeChildCallbackMap_.erase(pid);
205 }
206
InitNativeSpawnMsgPipe(std::shared_ptr<AppRunningManager> appRunningManager)207 void AppNativeSpawnManager::InitNativeSpawnMsgPipe(std::shared_ptr<AppRunningManager> appRunningManager)
208 {
209 appRunningManager_ = appRunningManager;
210 int pipeFd[2];
211 if (pipe(pipeFd) != 0) {
212 TAG_LOGE(AAFwkTag::APPMGR, "create native pipe failed");
213 return;
214 }
215 nrFd_ = pipeFd[0];
216 nwFd_ = pipeFd[1];
217 int ret = WatchParameter(NATIVESPAWN_STARTED, AppNativeSpawnStartCallback, nullptr);
218 if (ret != 0) {
219 TAG_LOGE(AAFwkTag::APPMGR, "watch native parameter, ret :%{public}d", ret);
220 return;
221 }
222 ffrt_qos_t taskQos = 0;
223 ret = ffrt_epoll_ctl(taskQos, EPOLL_CTL_ADD, nrFd_, EPOLLIN, nullptr, ProcessSignalData);
224 if (ret != 0) {
225 TAG_LOGE(AAFwkTag::APPMGR, "ffrt_epoll_ctl failed, ret :%{public}d", ret);
226 close(nrFd_);
227 return;
228 }
229 TAG_LOGI(AAFwkTag::APPMGR, "Listen native signal msg ...");
230 }
231
GetChildRelation(int32_t childPid)232 int32_t AppNativeSpawnManager::GetChildRelation(int32_t childPid)
233 {
234 std::lock_guard lock(childRelationLock_);
235 auto iter = childRelationMap_.find(childPid);
236 if (iter != childRelationMap_.end()) {
237 return iter->second;
238 }
239 return 0;
240 }
241
AddChildRelation(int32_t childPid,int32_t parentPid)242 void AppNativeSpawnManager::AddChildRelation(int32_t childPid, int32_t parentPid)
243 {
244 std::lock_guard lock(childRelationLock_);
245 childRelationMap_[childPid] = parentPid;
246 }
247
RemoveChildRelation(int32_t childPid)248 void AppNativeSpawnManager::RemoveChildRelation(int32_t childPid)
249 {
250 std::lock_guard lock(childRelationLock_);
251 childRelationMap_.erase(childPid);
252 }
253 } // end AppExecFwk
254 } // end OHOS
255