1 /*
2  * Copyright (c) 2023 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 "firmware_result_process.h"
17 
18 #include <fstream>
19 #include <iostream>
20 #include <map>
21 #include <sstream>
22 #include <string>
23 #include <unistd.h>
24 
25 #include "string_utils.h"
26 #include "firmware_callback_utils.h"
27 #include "firmware_common.h"
28 #include "firmware_preferences_utils.h"
29 #include "firmware_task.h"
30 #include "firmware_task_operator.h"
31 #include "firmware_update_adapter.h"
32 #include "firmware_update_helper.h"
33 
34 namespace OHOS {
35 namespace UpdateEngine {
36 static const std::string UPDATER_RESULT_FILE = "/data/updater/updater_result";
37 constexpr int32_t SYMBOL_LENGTH = 1;
38 constexpr uint32_t UPDATE_SUCCESSED = 1;
39 constexpr uint32_t UPDATE_FAILED = 2;
40 constexpr size_t  PKG_PATH_INDEX = 0;
41 constexpr size_t  RESULT_INDEX = 1;
42 constexpr size_t  REASON_INDEX = 2;
43 
ParseResult(const std::vector<std::string> & results,std::string & value,size_t index)44 void FirmwareResultProcess::ParseResult(const std::vector<std::string> &results, std::string &value, size_t index)
45 {
46     if (index >= results.size()) {
47         return;
48     }
49     value = results[index];
50     StringUtils::Trim(value);
51 }
52 
GetUpdaterResult(const std::vector<FirmwareComponent> & components,std::map<std::string,UpdateResult> & resultMap)53 UpdateResultCode FirmwareResultProcess::GetUpdaterResult(const std::vector<FirmwareComponent> &components,
54     std::map<std::string, UpdateResult> &resultMap)
55 {
56     FIRMWARE_LOGE("GetUpdaterResult");
57     if (components.empty()) {
58         FIRMWARE_LOGE("components is empty");
59         return UpdateResultCode::FAILURE;
60     }
61     resultMap.clear();
62     std::ifstream infile;
63     infile.open(UPDATER_RESULT_FILE, std::ios_base::in);
64     if (!infile.is_open()) {
65         FIRMWARE_LOGE("open update status file fail!");
66         HandleFileError(resultMap, components);
67     } else {
68         std::string buffer;
69         while (!infile.eof()) {
70             getline(infile, buffer);
71             ParseUpdaterResultRecord(buffer, resultMap);
72         }
73         infile.close();
74     }
75     return HandleFileResults(resultMap, components);
76 }
77 
CompareVersion(const FirmwareComponent & component)78 UpdateResult FirmwareResultProcess::CompareVersion(const FirmwareComponent &component)
79 {
80     bool isResultSuccess = false;
81     isResultSuccess = component.versionNumber == FirmwareUpdateAdapter::GetDisplayVersion();
82     FIRMWARE_LOGI("component.versionNumber=%{pubilc}s, GetDisplayVersion=%{pubilc}s",
83         component.versionNumber.c_str(), FirmwareUpdateAdapter::GetDisplayVersion().c_str());
84     UpdateResult updateResult;
85     updateResult.spath = component.spath;
86     if (isResultSuccess) {
87         updateResult.result = UPDATER_RESULT_SUCCESS;
88         updateResult.reason = UPDATER_RESULT_SUCCESS_REASON;
89     } else {
90         updateResult.result = UPDATER_RESULT_FAILURE;
91         updateResult.reason = UPDATER_RESULT_FAILURE_REASON;
92     }
93     return updateResult;
94 }
95 
96 /*
97     /data/update/ota_package/firmware/versions/0856210b1bf14427a0706aff1bdd4aed/updater.zip|pass
98     /data/update/ota_package/firmware/versions/1faa6ba19df044449ab8a10cb05bf1a6/updater.zip|
99     fail:;02:145768,41554,454656487,1463ac:-1
100     /data/update/ota_package/firmware/versions/971c50415d604c80a170f911993c2e2a/updater.zip
101     spath为 /data/update/ota_package/firmware/versions/52e700cdd0974ee79c721dad4a54f119/updater.zip
102     result为 pass或者fail 没有则为空
103     reason为 ;02:145768,41554,454656487,1463ac:-1 没有则为空
104 */
ParseUpdaterResultRecord(const std::string & resultLine,std::map<std::string,UpdateResult> & resultMap)105 void FirmwareResultProcess::ParseUpdaterResultRecord(const std::string &resultLine,
106     std::map<std::string, UpdateResult> &resultMap)
107 {
108     FIRMWARE_LOGE("ParseUpdaterResultRecord");
109     if (resultLine.empty()) {
110         FIRMWARE_LOGE("resultLine is null");
111         return;
112     }
113     UpdateResult updateResult;
114     std::vector<std::string> results;
115     std::stringstream stringStream(resultLine);
116     std::string token;
117     while (std::getline(stringStream, token, '|')) {
118         results.push_back(token);
119     }
120 
121     ParseResult(results, updateResult.spath, PKG_PATH_INDEX);
122     ParseResult(results, updateResult.result, RESULT_INDEX);
123     ParseResult(results, updateResult.reason, REASON_INDEX);
124 
125     auto colonPlace = updateResult.result.find_first_of(":");
126     if (colonPlace != std::string::npos) {
127         updateResult.result = updateResult.result.substr(0, colonPlace);
128         updateResult.reason = results[RESULT_INDEX].substr(colonPlace + SYMBOL_LENGTH);
129     }
130     StringUtils::Trim(updateResult.spath);
131     StringUtils::Trim(updateResult.result);
132     StringUtils::Trim(updateResult.reason);
133     resultMap.emplace(std::make_pair(updateResult.spath, updateResult));
134 }
135 
HandleFileError(std::map<std::string,UpdateResult> & resultMap,const std::vector<FirmwareComponent> & components)136 void FirmwareResultProcess::HandleFileError(std::map<std::string, UpdateResult> &resultMap,
137     const std::vector<FirmwareComponent> &components)
138 {
139     resultMap.clear();
140     for (const auto &component : components) {
141         UpdateResult updateResult = CompareVersion(component);
142         resultMap.emplace(std::make_pair(updateResult.spath, updateResult));
143     }
144 }
145 
HandleFileResults(std::map<std::string,UpdateResult> & resultMap,const std::vector<FirmwareComponent> & components)146 UpdateResultCode FirmwareResultProcess::HandleFileResults(std::map<std::string, UpdateResult> &resultMap,
147     const std::vector<FirmwareComponent> &components)
148 {
149     FirmwareTask task;
150     FirmwareTaskOperator().QueryTask(task);
151     if (!task.isExistTask) {
152         FIRMWARE_LOGI("HandleFileResults has no task");
153         return UpdateResultCode::FAILURE;
154     }
155     uint32_t hotaUpdateResult = 0;
156     for (const auto &component : components) {
157         std::string updateResultStatus;
158         auto result = resultMap.find(component.spath);
159         if (result == resultMap.end()) {
160             UpdateResult updateResult = CompareVersion(component);
161             resultMap.emplace(std::make_pair(updateResult.spath, updateResult));
162             FIRMWARE_LOGE("spath %{public}s, result %{public}s", component.spath.c_str(), updateResult.result.c_str());
163             updateResultStatus = updateResult.result;
164         } else {
165             updateResultStatus = result->second.result;
166         }
167         hotaUpdateResult |= updateResultStatus == UPDATER_RESULT_SUCCESS ? UPDATE_SUCCESSED : UPDATE_FAILED;
168     }
169 
170     if (task.combinationType == CombinationType::HOTA) {
171         return hotaUpdateResult == UPDATE_SUCCESSED ? UpdateResultCode::SUCCESS : UpdateResultCode::FAILURE;
172     }
173 
174     if (hotaUpdateResult != UPDATE_SUCCESSED) {
175         return UpdateResultCode::FAILURE;
176     }
177     return UpdateResultCode::SUCCESS;
178 }
179 } // namespace UpdateEngine
180 } // namespace OHOS
181