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