• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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