* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "daemon_updater.h"
#include "daemon_common.h"
#include "flashd_define.h"
#include "hdi/client/update_hdi_client.h"
#include "updater/updater.h"
#include "updater/updater_const.h"
using namespace std;
namespace Hdc {
namespace {
constexpr uint8_t PAYLOAD_FIX_RESERVER = 64;
}
std::atomic<bool> DaemonUpdater::isRunning_ = false;
DaemonUpdater::DaemonUpdater(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo)
{
commandBegin = CMD_UPDATER_BEGIN;
commandData = CMD_UPDATER_DATA;
}
DaemonUpdater::~DaemonUpdater()
{
FLASHD_LOGI("~DaemonUpdater refCount %d", refCount.load());
}
bool DaemonUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
{
if (IsDeviceLocked()) {
std::string echo = "operation is not allowed";
vector<uint8_t> buffer;
buffer.push_back(command);
buffer.push_back(Hdc::MSG_FAIL);
buffer.insert(buffer.end(), echo.begin(), echo.end());
SendToAnother(Hdc::CMD_UPDATER_FINISH, buffer.data(), buffer.size());
FLASHD_LOGE("The devic is locked and operation is not allowed");
return false;
}
if (!isInit_) {
Init();
isInit_ = true;
}
auto iter = cmdFunc_.find(command);
if (iter == cmdFunc_.end()) {
FLASHD_LOGE("command is invalid, command = %d", command);
return false;
}
iter->second(payload, payloadSize);
return true;
}
bool DaemonUpdater::SendToHost(Flashd::CmdType type, Flashd::UpdaterState state, const std::string &msg)
{
if (!DaemonUpdater::isRunning_) {
FLASHD_LOGW("flasd is not runing");
return true;
}
if (state == Flashd::UpdaterState::DOING) {
uint32_t temp = 0;
std::stringstream percentageStream(msg);
if (!(percentageStream >> temp)) {
temp = 0;
}
uint8_t percentage = static_cast<uint8_t>(temp);
SendToAnother(Hdc::CMD_UPDATER_PROGRESS, &percentage, sizeof(percentage));
return true;
}
if (state == Flashd::UpdaterState::FAIL || state == Flashd::UpdaterState::SUCCESS) {
uint8_t percentage = (state == Flashd::UpdaterState::SUCCESS) ? Flashd::PERCENT_FINISH : Flashd::PERCENT_CLEAR;
SendToAnother(Hdc::CMD_UPDATER_PROGRESS, &percentage, sizeof(percentage));
std::string echo = Hdc::Base::ReplaceAll(msg, "\n", " ");
vector<uint8_t> buffer;
buffer.push_back(static_cast<uint8_t>(type));
buffer.push_back((state == Flashd::UpdaterState::SUCCESS) ? Hdc::MSG_OK : Hdc::MSG_FAIL);
buffer.insert(buffer.end(), echo.begin(), echo.end());
SendToAnother(Hdc::CMD_UPDATER_FINISH, buffer.data(), buffer.size());
TaskFinish();
if (commander_ != nullptr) {
commander_->PostCommand();
}
DaemonUpdater::isRunning_ = false;
}
return true;
}
std::unique_ptr<Flashd::Commander> DaemonUpdater::CreateCommander(const std::string &cmd)
{
if (DaemonUpdater::isRunning_) {
FLASHD_LOGE("flashd has been running");
return nullptr;
}
DaemonUpdater::isRunning_ = true;
auto callback = [this](Flashd::CmdType type, Flashd::UpdaterState state, const std::string &msg) {
SendToHost(type, state, msg);
};
return Flashd::CommanderFactory::GetInstance().CreateCommander(cmd, callback);
}
void DaemonUpdater::CheckCommand(const uint8_t *payload, int payloadSize)
{
if (payloadSize < static_cast<int>(sizeof(int64_t))) {
FLASHD_LOGE("payloadSize is invalid");
return;
}
string bufString(reinterpret_cast<const char *>(payload + sizeof(int64_t)), payloadSize - sizeof(int64_t));
SerialStruct::ParseFromString(ctxNow.transferConfig, bufString);
ctxNow.master = false;
ctxNow.fsOpenReq.data = &ctxNow;
ctxNow.fileSize = ctxNow.transferConfig.fileSize;
FLASHD_LOGI("functionName = %s, options = %s, fileSize = %u", ctxNow.transferConfig.functionName.c_str(),
ctxNow.transferConfig.options.c_str(), ctxNow.transferConfig.fileSize);
commander_ = CreateCommander(ctxNow.transferConfig.functionName.c_str());
if (commander_ == nullptr) {
FLASHD_LOGE("commander_ is null for cmd = %s", ctxNow.transferConfig.functionName.c_str());
return;
}
commander_->DoCommand(ctxNow.transferConfig.options, ctxNow.transferConfig.fileSize);
SendToAnother(commandBegin, nullptr, 0);
refCount++;
}
void DaemonUpdater::DataCommand(const uint8_t *payload, int payloadSize) const
{
if (commander_ == nullptr) {
FLASHD_LOGE("commander_ is null");
return;
}
if (payloadSize <= PAYLOAD_FIX_RESERVER) {
FLASHD_LOGE("payloadSize is invaild");
return;
}
string serialStrring(reinterpret_cast<const char *>(payload), PAYLOAD_FIX_RESERVER);
TransferPayload pld = {};
SerialStruct::ParseFromString(pld, serialStrring);
if (pld.uncompressSize + PAYLOAD_FIX_RESERVER > static_cast<uint32_t>(payloadSize)) {
FLASHD_LOGE("uncompressSize is invaild %d", pld.uncompressSize);
return;
}
commander_->DoCommand(payload + PAYLOAD_FIX_RESERVER, pld.uncompressSize);
}
void DaemonUpdater::EraseCommand(const uint8_t *payload, int payloadSize)
{
commander_ = CreateCommander(CMDSTR_ERASE_PARTITION);
if (commander_ == nullptr) {
FLASHD_LOGE("commander_ is null for cmd = %s", CMDSTR_ERASE_PARTITION);
return;
}
commander_->DoCommand(payload, payloadSize);
}
void DaemonUpdater::FormatCommand(const uint8_t *payload, int payloadSize)
{
commander_ = CreateCommander(CMDSTR_FORMAT_PARTITION);
if (commander_ == nullptr) {
FLASHD_LOGE("commander_ is null for cmd = %s", CMDSTR_FORMAT_PARTITION);
return;
}
commander_->DoCommand(payload, payloadSize);
}
void DaemonUpdater::Init()
{
cmdFunc_.emplace(CMD_UPDATER_CHECK, bind(&DaemonUpdater::CheckCommand, this, placeholders::_1, placeholders::_2));
cmdFunc_.emplace(CMD_UPDATER_DATA, bind(&DaemonUpdater::DataCommand, this, placeholders::_1, placeholders::_2));
cmdFunc_.emplace(CMD_UPDATER_ERASE, bind(&DaemonUpdater::EraseCommand, this, placeholders::_1, placeholders::_2));
cmdFunc_.emplace(CMD_UPDATER_FORMAT, bind(&DaemonUpdater::FormatCommand, this, placeholders::_1, placeholders::_2));
}
bool DaemonUpdater::IsDeviceLocked() const
{
bool isLocked = true;
if (auto ret = Updater::UpdateHdiClient::GetInstance().GetLockStatus(isLocked); ret != 0) {
FLASHD_LOGE("GetLockStatus fail, ret = %d", ret);
return true;
}
return isLocked;
}
InvalidDaemon::InvalidDaemon(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo)
{
FLASHD_LOGI("InvalidDaemon init");
}
InvalidDaemon::~InvalidDaemon()
{
FLASHD_LOGI("~InvalidDaemon refCount %d", refCount.load());
}
bool InvalidDaemon::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
{
std::string echo = "operation is not allowed";
vector<uint8_t> buffer;
buffer.push_back(command);
buffer.push_back(Hdc::MSG_FAIL);
buffer.insert(buffer.end(), echo.begin(), echo.end());
LogMsg(MSG_FAIL, "Operation is not allowed");
TaskFinish();
FLASHD_LOGE("The operation is not allowed");
return false;
}
}