1 /*
2 * Copyright (C) 2021 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 #include "host_app.h"
16
17 namespace Hdc {
HdcHostApp(HTaskInfo hTaskInfo)18 HdcHostApp::HdcHostApp(HTaskInfo hTaskInfo)
19 : HdcTransferBase(hTaskInfo)
20 {
21 commandBegin = CMD_APP_BEGIN;
22 commandData = CMD_APP_DATA;
23 }
24
~HdcHostApp()25 HdcHostApp::~HdcHostApp()
26 {
27 }
28
BeginInstall(CtxFile * context,const char * command)29 bool HdcHostApp::BeginInstall(CtxFile *context, const char *command)
30 {
31 int argc = 0;
32 bool ret = false;
33 string options;
34 char **argv = Base::SplitCommandToArgs(command, &argc);
35 if (argc < 1) {
36 goto Finish;
37 }
38
39 for (int i = 0; i < argc; ++i) {
40 if (!strcmp(argv[i], CMD_OPTION_CLIENTCWD.c_str())) {
41 if (i + 1 < argc) {
42 context->transferConfig.clientCwd = argv[i + 1];
43 i += 1; // add content index
44 }
45 } else if (!strncmp(argv[i], "-", 1)) {
46 if (options.size()) {
47 options += " ";
48 }
49 options += argv[i];
50 } else {
51 string path = argv[i];
52 ExtractRelativePath(context->transferConfig.clientCwd, path);
53 if (MatchPackageExtendName(path, ".hap")) {
54 context->taskQueue.push_back(path);
55 } else {
56 GetSubFiles(argv[i], ".hap", &context->taskQueue);
57 }
58 }
59 }
60 if (!context->taskQueue.size()) {
61 LogMsg(MSG_FAIL, "Not any installation package was found");
62 goto Finish;
63 }
64 // remove repeate
65 sort(context->taskQueue.begin(), context->taskQueue.end());
66 context->taskQueue.erase(unique(context->taskQueue.begin(), context->taskQueue.end()), context->taskQueue.end());
67
68 context->transferConfig.options = options;
69 context->transferConfig.functionName = CMDSTR_APP_INSTALL;
70 RunQueue(context);
71 ret = true;
72 Finish:
73 if (argv) {
74 delete[]((char *)argv);
75 }
76 return ret;
77 }
78
BeginSideload(CtxFile * context,const char * localPath)79 bool HdcHostApp::BeginSideload(CtxFile *context, const char *localPath)
80 {
81 bool ret = false;
82 context->transferConfig.functionName = CMDSTR_APP_SIDELOAD;
83 context->taskQueue.push_back(localPath);
84 RunQueue(context);
85 ret = true;
86 return ret;
87 }
88
RunQueue(CtxFile * context)89 void HdcHostApp::RunQueue(CtxFile *context)
90 {
91 ++refCount;
92 context->localPath = context->taskQueue.back();
93 uv_fs_open(loopTask, &context->fsOpenReq, context->localPath.c_str(), O_RDONLY, 0, OnFileOpen);
94 context->master = true;
95 }
96
CheckMaster(CtxFile * context)97 void HdcHostApp::CheckMaster(CtxFile *context)
98 {
99 uv_fs_t fs = {};
100 uv_fs_fstat(nullptr, &fs, context->fsOpenReq.result, nullptr);
101 context->transferConfig.fileSize = fs.statbuf.st_size;
102 uv_fs_req_cleanup(&fs);
103
104 context->transferConfig.optionalName
105 = Base::GetRandomString(9); // Prevent the name of illegal APP leads to pm unable to install
106 if (context->localPath.find(".hap") != (size_t)-1) {
107 context->transferConfig.optionalName += ".hap";
108 } else {
109 context->transferConfig.optionalName += ".bundle";
110 }
111 string bufString = SerialStruct::SerializeToString(context->transferConfig);
112 SendToAnother(CMD_APP_CHECK, (uint8_t *)bufString.c_str(), bufString.size());
113 }
114
CheckInstallContinue(AppModType mode,bool lastResult,const char * msg)115 bool HdcHostApp::CheckInstallContinue(AppModType mode, bool lastResult, const char *msg)
116 {
117 string modeDesc;
118 switch (mode) {
119 case APPMOD_INSTALL:
120 modeDesc = "App install";
121 break;
122 case APPMOD_UNINSTALL:
123 modeDesc = "App uninstall";
124 break;
125 case APPMOD_SIDELOAD:
126 modeDesc = "Side load";
127 break;
128 default:
129 modeDesc = "Unknown";
130 break;
131 }
132 if (ctxNow.taskQueue.size() > 0) {
133 ctxNow.taskQueue.pop_back();
134 }
135 LogMsg(MSG_INFO, "%s path:%s, queuesize:%d, msg:%s", modeDesc.c_str(), ctxNow.localPath.c_str(),
136 ctxNow.taskQueue.size(), msg);
137 if (singalStop || !ctxNow.taskQueue.size()) {
138 LogMsg(MSG_OK, "AppMod finish");
139 return false;
140 }
141 RunQueue(&ctxNow);
142 return true;
143 }
144
CommandDispatch(const uint16_t command,uint8_t * payload,const int payloadSize)145 bool HdcHostApp::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
146 {
147 if (!HdcTransferBase::CommandDispatch(command, payload, payloadSize)) {
148 return false;
149 }
150 bool ret = true;
151 constexpr int cmdOffset = 2;
152 switch (command) {
153 case CMD_APP_INIT: {
154 ret = BeginInstall(&ctxNow, (const char *)payload);
155 break;
156 }
157 case CMD_APP_FINISH: {
158 AppModType mode = (AppModType)payload[0];
159 bool result = (bool)payload[1];
160 string s(reinterpret_cast<char *>(payload + cmdOffset), payloadSize - cmdOffset);
161 ret = CheckInstallContinue(mode, result, s.c_str());
162 break;
163 }
164 case CMD_APP_UNINSTALL: {
165 SendToAnother(CMD_APP_UNINSTALL, payload, payloadSize);
166 ctxNow.taskQueue.push_back(reinterpret_cast<char *>(payload)); // just compatible
167 break;
168 }
169 case CMD_APP_SIDELOAD: {
170 BeginSideload(&ctxNow, (const char *)payload);
171 break;
172 }
173 default:
174 break;
175 }
176 return ret;
177 };
178 }
179