• 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