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