1 /*
2  * Copyright (c) 2022 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 "aafwk_app_mgr_client_adapter_impl.h"
17 
18 #include <chrono>
19 #include <thread>
20 
21 #include "aafwk_browser_host_impl.h"
22 #include "aafwk_render_scheduler_impl.h"
23 #include "nweb_log.h"
24 
25 namespace {
26 constexpr int GET_TERMINATION_STATUS_MAX_CNT = 5;
27 constexpr int START_RENDER_PROCESS_MAX_CNT = 10;
28 constexpr int SLEEP_FOR_MILLI_SECONDS_CNT = 10;
29 constexpr int RET_ALREADY_EXIST_RENDER = 8454244; // copy from ability_runtime
30 } // namespace
31 
32 namespace OHOS::NWeb {
33 const std::string GPU_PROCESS_TYPE = "gpu-process";
AafwkAppMgrClientAdapterImpl()34 AafwkAppMgrClientAdapterImpl::AafwkAppMgrClientAdapterImpl()
35     : appMgrClient_(std::make_unique<AppExecFwk::AppMgrClient>())
36 {}
37 
StartRenderProcess(const std::string & renderParam,int32_t ipcFd,int32_t sharedFd,int32_t crashFd,pid_t & renderPid)38 int AafwkAppMgrClientAdapterImpl::StartRenderProcess(
39     const std::string& renderParam, int32_t ipcFd, int32_t sharedFd, int32_t crashFd, pid_t& renderPid)
40 {
41     if (appMgrClient_ == nullptr) {
42         WVLOG_E("app mgr client is nullptr.");
43         return -1;
44     }
45 
46     int retryCnt = 0;
47     int ret;
48     do {
49         ret = appMgrClient_->StartRenderProcess(renderParam, ipcFd, sharedFd, crashFd, renderPid, false);
50         if (ret == RET_ALREADY_EXIST_RENDER) {
51             WVLOG_E("app mgr client start render process failed, render process already exist.");
52             std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_MILLI_SECONDS_CNT));
53             continue;
54         }
55         if (ret != 0) {
56             WVLOG_E("app mgr client start render process failed, ret = %{public}d.", ret);
57             return -1;
58         }
59     } while (++retryCnt < START_RENDER_PROCESS_MAX_CNT && ret != 0);
60 
61     if (ret != 0) {
62         WVLOG_E("over max retry times, app mgr client start render process failed, ret = %{public}d.", ret);
63         return -1;
64     }
65 
66     return 0;
67 }
68 
AttachRenderProcess(std::shared_ptr<AafwkRenderSchedulerHostAdapter> adapter)69 void AafwkAppMgrClientAdapterImpl::AttachRenderProcess(std::shared_ptr<AafwkRenderSchedulerHostAdapter> adapter)
70 {
71     if (appMgrClient_ == nullptr) {
72         WVLOG_E("app mgr client is nullptr.");
73         return;
74     }
75 
76     if (adapter == nullptr) {
77         WVLOG_E("render scheduler is nullptr.");
78         return;
79     }
80 
81     AafwkRenderSchedulerImpl *renderScheduler = new (std::nothrow) AafwkRenderSchedulerImpl(adapter);
82     if (renderScheduler == nullptr) {
83         WVLOG_E("new AafwkRenderSchedulerImpl failed.");
84         return;
85     }
86 
87     appMgrClient_->AttachRenderProcess(renderScheduler);
88 }
89 
GetRenderProcessTerminationStatus(pid_t renderPid,int & status)90 int AafwkAppMgrClientAdapterImpl::GetRenderProcessTerminationStatus(pid_t renderPid, int &status)
91 {
92     if (appMgrClient_ == nullptr) {
93         WVLOG_E("app mgr client is nullptr.");
94         return -1;
95     }
96 
97     int retryCnt = 0;
98     do {
99         int ret = appMgrClient_->GetRenderProcessTerminationStatus(renderPid, status);
100         if (ret != 0) {
101             WVLOG_E("app mgr client get render process termination status failed, ret = %{public}d.", ret);
102             return -1;
103         }
104     } while (status < 0 && ++retryCnt < GET_TERMINATION_STATUS_MAX_CNT);
105 
106     if (status < 0) {
107         WVLOG_E("render process termination status invalid, status = %{public}d.", status);
108         return -1;
109     }
110 
111     return 0;
112 }
113 
StartChildProcess(const std::string & renderParam,int32_t ipcFd,int32_t sharedFd,int32_t crashFd,pid_t & renderPid,const std::string & processType)114 int AafwkAppMgrClientAdapterImpl::StartChildProcess(
115     const std::string& renderParam, int32_t ipcFd, int32_t sharedFd,
116     int32_t crashFd, pid_t& renderPid, const std::string& processType)
117 {
118     if (appMgrClient_ == nullptr) {
119         WVLOG_E("app mgr client is nullptr.");
120         return -1;
121     }
122 
123     bool isGPU = false;
124     if (processType == GPU_PROCESS_TYPE) {
125         isGPU = true;
126     }
127 
128     int retryCnt = 0;
129     int ret;
130     do {
131         ret = appMgrClient_->StartRenderProcess(renderParam, ipcFd, sharedFd, crashFd, renderPid, isGPU);
132         if (ret == RET_ALREADY_EXIST_RENDER) {
133             WVLOG_E("app mgr client start %{public}s process failed, process already exist.", processType.c_str());
134             std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_FOR_MILLI_SECONDS_CNT));
135             continue;
136         }
137         if (ret != 0) {
138             WVLOG_E("app mgr client start render process failed, ret = %{public}d.", ret);
139             return -1;
140         }
141     } while (++retryCnt < START_RENDER_PROCESS_MAX_CNT && ret != 0);
142 
143     if (ret != 0) {
144         WVLOG_E("over max retry times, app mgr client start render process failed, ret = %{public}d.", ret);
145         return -1;
146     }
147 
148     return 0;
149 }
150 
SaveBrowserConnect(std::shared_ptr<AafwkBrowserHostAdapter> adapter)151 void AafwkAppMgrClientAdapterImpl::SaveBrowserConnect(std::shared_ptr<AafwkBrowserHostAdapter> adapter)
152 {
153     if (appMgrClient_ == nullptr) {
154         WVLOG_E("app mgr client is nullptr.");
155         return;
156     }
157 
158     if (adapter == nullptr) {
159         WVLOG_E("browser connect is nullptr.");
160         return;
161     }
162 
163     AafwkBrowserHostImpl *browser = new (std::nothrow) AafwkBrowserHostImpl(adapter);
164     if (browser == nullptr) {
165         WVLOG_E("create new AafwkBrowserHostImpl failed!");
166     }
167     WVLOG_I("AafwkAppMgrClientAdapterImpl SaveBrowserConnect success!");
168     appMgrClient_->SaveBrowserChannel(browser);
169 }
170 } // namespace OHOS::NWeb
171