1 /*
2 * Copyright (c) 2022-2024 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 "quick_fix_manager_proxy.h"
17
18 #include <cerrno>
19 #include <fcntl.h>
20 #include <unistd.h>
21
22 #include "app_log_tag_wrapper.h"
23 #include "app_log_wrapper.h"
24 #include "appexecfwk_errors.h"
25 #include "bundle_file_util.h"
26 #include "directory_ex.h"
27 #include "hitrace_meter.h"
28 #include "ipc_types.h"
29
30 namespace OHOS {
31 namespace AppExecFwk {
32 namespace {
33 const std::string SEPARATOR = "/";
34 const int32_t DEFAULT_BUFFER_SIZE = 65536;
35 }
36
QuickFixManagerProxy(const sptr<IRemoteObject> & object)37 QuickFixManagerProxy::QuickFixManagerProxy(const sptr<IRemoteObject> &object) : IRemoteProxy<IQuickFixManager>(object)
38 {
39 LOG_I(BMS_TAG_DEFAULT, "create QuickFixManagerProxy");
40 }
41
~QuickFixManagerProxy()42 QuickFixManagerProxy::~QuickFixManagerProxy()
43 {
44 LOG_I(BMS_TAG_DEFAULT, "destroy QuickFixManagerProxy");
45 }
46
DeployQuickFix(const std::vector<std::string> & bundleFilePaths,const sptr<IQuickFixStatusCallback> & statusCallback,bool isDebug,const std::string & inputTargetPath)47 ErrCode QuickFixManagerProxy::DeployQuickFix(const std::vector<std::string> &bundleFilePaths,
48 const sptr<IQuickFixStatusCallback> &statusCallback, bool isDebug, const std::string &inputTargetPath)
49 {
50 LOG_I(BMS_TAG_DEFAULT, "begin to call DeployQuickFix");
51 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
52
53 if (bundleFilePaths.empty() || (statusCallback == nullptr)) {
54 LOG_E(BMS_TAG_DEFAULT, "DeployQuickFix failed due to params error");
55 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
56 }
57
58 std::string targetPath = inputTargetPath;
59 if (targetPath.find(".") != std::string::npos ||
60 targetPath.find("..") != std::string::npos ||
61 targetPath.find("/") != std::string::npos) {
62 LOG_E(BMS_TAG_DEFAULT, "input targetPath is invalid");
63 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
64 }
65
66 MessageParcel data;
67 if (!data.WriteInterfaceToken(GetDescriptor())) {
68 LOG_E(BMS_TAG_DEFAULT, "WriteInterfaceToken failed");
69 return ERR_APPEXECFWK_PARCEL_ERROR;
70 }
71 if (!data.WriteStringVector(bundleFilePaths)) {
72 LOG_E(BMS_TAG_DEFAULT, "write bundleFilePaths failed");
73 return ERR_APPEXECFWK_PARCEL_ERROR;
74 }
75 if (!data.WriteBool(isDebug)) {
76 LOG_E(BMS_TAG_DEFAULT, "write isDebug failed");
77 return ERR_APPEXECFWK_PARCEL_ERROR;
78 }
79 if (!data.WriteString(targetPath)) {
80 LOG_E(BMS_TAG_DEFAULT, "write targetPath failed");
81 return ERR_APPEXECFWK_PARCEL_ERROR;
82 }
83 if (!data.WriteRemoteObject(statusCallback->AsObject())) {
84 LOG_E(BMS_TAG_DEFAULT, "write parcel failed");
85 return ERR_APPEXECFWK_PARCEL_ERROR;
86 }
87
88 MessageParcel reply;
89 if (!SendRequest(QuickFixManagerInterfaceCode::DEPLOY_QUICK_FIX, data, reply)) {
90 LOG_E(BMS_TAG_DEFAULT, "SendRequest failed");
91 return ERR_BUNDLEMANAGER_QUICK_FIX_SEND_REQUEST_FAILED;
92 }
93
94 return reply.ReadInt32();
95 }
96
SwitchQuickFix(const std::string & bundleName,bool enable,const sptr<IQuickFixStatusCallback> & statusCallback)97 ErrCode QuickFixManagerProxy::SwitchQuickFix(const std::string &bundleName, bool enable,
98 const sptr<IQuickFixStatusCallback> &statusCallback)
99 {
100 LOG_I(BMS_TAG_DEFAULT, "begin to call SwitchQuickFix");
101 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
102
103 if (bundleName.empty() || (statusCallback == nullptr)) {
104 LOG_E(BMS_TAG_DEFAULT, "SwitchQuickFix failed due to params error");
105 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
106 }
107
108 MessageParcel data;
109 if (!data.WriteInterfaceToken(GetDescriptor())) {
110 LOG_E(BMS_TAG_DEFAULT, "WriteInterfaceToken failed");
111 return ERR_APPEXECFWK_PARCEL_ERROR;
112 }
113 if (!data.WriteString(bundleName)) {
114 LOG_E(BMS_TAG_DEFAULT, "write bundleName failed");
115 return ERR_APPEXECFWK_PARCEL_ERROR;
116 }
117 if (!data.WriteBool(enable)) {
118 LOG_E(BMS_TAG_DEFAULT, "write enable failed");
119 return ERR_APPEXECFWK_PARCEL_ERROR;
120 }
121 if (!data.WriteRemoteObject(statusCallback->AsObject())) {
122 LOG_E(BMS_TAG_DEFAULT, "write parcel failed");
123 return ERR_APPEXECFWK_PARCEL_ERROR;
124 }
125
126 MessageParcel reply;
127 if (!SendRequest(QuickFixManagerInterfaceCode::SWITCH_QUICK_FIX, data, reply)) {
128 LOG_E(BMS_TAG_DEFAULT, "SendRequest failed");
129 return ERR_BUNDLEMANAGER_QUICK_FIX_SEND_REQUEST_FAILED;
130 }
131
132 return reply.ReadInt32();
133 }
134
DeleteQuickFix(const std::string & bundleName,const sptr<IQuickFixStatusCallback> & statusCallback)135 ErrCode QuickFixManagerProxy::DeleteQuickFix(const std::string &bundleName,
136 const sptr<IQuickFixStatusCallback> &statusCallback)
137 {
138 LOG_I(BMS_TAG_DEFAULT, "begin to call DeleteQuickFix");
139 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
140
141 if (bundleName.empty() || (statusCallback == nullptr)) {
142 LOG_E(BMS_TAG_DEFAULT, "DeleteQuickFix failed due to params error");
143 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
144 }
145
146 MessageParcel data;
147 if (!data.WriteInterfaceToken(GetDescriptor())) {
148 LOG_E(BMS_TAG_DEFAULT, "WriteInterfaceToken failed");
149 return ERR_APPEXECFWK_PARCEL_ERROR;
150 }
151 if (!data.WriteString(bundleName)) {
152 LOG_E(BMS_TAG_DEFAULT, "write bundleName failed");
153 return ERR_APPEXECFWK_PARCEL_ERROR;
154 }
155 if (!data.WriteRemoteObject(statusCallback->AsObject())) {
156 LOG_E(BMS_TAG_DEFAULT, "write parcel failed");
157 return ERR_APPEXECFWK_PARCEL_ERROR;
158 }
159
160 MessageParcel reply;
161 if (!SendRequest(QuickFixManagerInterfaceCode::DELETE_QUICK_FIX, data, reply)) {
162 LOG_E(BMS_TAG_DEFAULT, "SendRequest failed");
163 return ERR_BUNDLEMANAGER_QUICK_FIX_SEND_REQUEST_FAILED;
164 }
165
166 return reply.ReadInt32();
167 }
168
CreateFd(const std::string & fileName,int32_t & fd,std::string & path)169 ErrCode QuickFixManagerProxy::CreateFd(const std::string &fileName, int32_t &fd, std::string &path)
170 {
171 LOG_D(BMS_TAG_DEFAULT, "begin to create fd");
172 if (fileName.empty()) {
173 LOG_E(BMS_TAG_DEFAULT, "fileName is empty");
174 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
175 }
176 MessageParcel data;
177 if (!data.WriteInterfaceToken(GetDescriptor())) {
178 LOG_E(BMS_TAG_DEFAULT, "write interface token failed");
179 return ERR_APPEXECFWK_PARCEL_ERROR;
180 }
181 if (!data.WriteString(fileName)) {
182 LOG_E(BMS_TAG_DEFAULT, "write fileName failed");
183 return ERR_APPEXECFWK_PARCEL_ERROR;
184 }
185 MessageParcel reply;
186 if (!SendRequest(QuickFixManagerInterfaceCode::CREATE_FD, data, reply)) {
187 LOG_E(BMS_TAG_DEFAULT, "send request failed");
188 return ERR_APPEXECFWK_PARCEL_ERROR;
189 }
190 auto ret = reply.ReadInt32();
191 if (ret != ERR_OK) {
192 LOG_E(BMS_TAG_DEFAULT, "reply return false");
193 return ret;
194 }
195 fd = reply.ReadFileDescriptor();
196 if (fd < 0) {
197 LOG_E(BMS_TAG_DEFAULT, "invalid fd");
198 return ERR_BUNDLEMANAGER_QUICK_FIX_CREATE_FD_FAILED;
199 }
200 path = reply.ReadString();
201 if (path.empty()) {
202 LOG_E(BMS_TAG_DEFAULT, "invalid path");
203 close(fd);
204 return ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_TARGET_DIR;
205 }
206 LOG_D(BMS_TAG_DEFAULT, "create fd success");
207 return ERR_OK;
208 }
209
CopyFiles(const std::vector<std::string> & sourceFiles,std::vector<std::string> & destFiles)210 ErrCode QuickFixManagerProxy::CopyFiles(
211 const std::vector<std::string> &sourceFiles, std::vector<std::string> &destFiles)
212 {
213 LOG_D(BMS_TAG_DEFAULT, "begin to copy files");
214 if (sourceFiles.empty()) {
215 LOG_E(BMS_TAG_DEFAULT, "sourceFiles empty");
216 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
217 }
218 std::vector<std::string> hqfFilePaths;
219 if (!BundleFileUtil::CheckFilePath(sourceFiles, hqfFilePaths)) {
220 LOG_E(BMS_TAG_DEFAULT, "CopyFiles CheckFilePath failed");
221 return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
222 }
223 for (const std::string &sourcePath : hqfFilePaths) {
224 size_t pos = sourcePath.find_last_of(SEPARATOR);
225 if (pos == std::string::npos) {
226 LOG_E(BMS_TAG_DEFAULT, "invalid sourcePath");
227 return ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_PATH;
228 }
229 std::string fileName = sourcePath.substr(pos + 1);
230 LOG_D(BMS_TAG_DEFAULT, "sourcePath:%{private}s fileName:%{private}s", sourcePath.c_str(), fileName.c_str());
231 int32_t sourceFd = open(sourcePath.c_str(), O_RDONLY);
232 if (sourceFd < 0) {
233 LOG_E(BMS_TAG_DEFAULT, "open file failed, errno:%{public}d", errno);
234 return ERR_BUNDLEMANAGER_QUICK_FIX_OPEN_SOURCE_FILE_FAILED;
235 }
236 int32_t destFd = -1;
237 std::string destPath;
238 auto ret = CreateFd(fileName, destFd, destPath);
239 if ((ret != ERR_OK) || (destFd < 0) || (destPath.empty())) {
240 LOG_E(BMS_TAG_DEFAULT, "create fd failed");
241 close(sourceFd);
242 return ret;
243 }
244 char buffer[DEFAULT_BUFFER_SIZE] = {0};
245 int offset = -1;
246 while ((offset = read(sourceFd, buffer, sizeof(buffer))) > 0) {
247 if (write(destFd, buffer, offset) < 0) {
248 LOG_E(BMS_TAG_DEFAULT, "write file to the temp dir failed, errno %{public}d", errno);
249 close(sourceFd);
250 close(destFd);
251 return ERR_BUNDLEMANAGER_QUICK_FIX_WRITE_FILE_FAILED;
252 }
253 }
254 destFiles.emplace_back(destPath);
255 close(sourceFd);
256 fsync(destFd);
257 close(destFd);
258 }
259 LOG_D(BMS_TAG_DEFAULT, "copy files success");
260 return ERR_OK;
261 }
262
SendRequest(QuickFixManagerInterfaceCode code,MessageParcel & data,MessageParcel & reply)263 bool QuickFixManagerProxy::SendRequest(QuickFixManagerInterfaceCode code, MessageParcel &data, MessageParcel &reply)
264 {
265 MessageOption option(MessageOption::TF_SYNC);
266 sptr<IRemoteObject> remote = Remote();
267 if (remote == nullptr) {
268 LOG_E(BMS_TAG_DEFAULT, "failed to send request %{public}hhu due to remote object null", code);
269 return false;
270 }
271 int32_t result = remote->SendRequest(static_cast<uint32_t>(code), data, reply, option);
272 if (result != NO_ERROR) {
273 LOG_E(BMS_TAG_DEFAULT, "receive error code %{public}d in transact %{public}hhu", result, code);
274 return false;
275 }
276 return true;
277 }
278 } // AppExecFwk
279 } // OHOS