You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1527 lines
46 KiB
1527 lines
46 KiB
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#define LOG_TAG "NanohubHAL"
|
|
|
|
#include "file.h"
|
|
#include <json/json.h>
|
|
|
|
#include <cassert>
|
|
#include <cerrno>
|
|
#include <cinttypes>
|
|
#include <string>
|
|
|
|
#include <endian.h>
|
|
|
|
#include <vector>
|
|
|
|
#include <log/log.h>
|
|
|
|
#include <endian.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <media/stagefright/foundation/ADebug.h>
|
|
|
|
#include <hardware/context_hub.h>
|
|
#include "nanohub_perdevice.h"
|
|
#include "system_comms.h"
|
|
#include "nanohubhal.h"
|
|
|
|
#define CHRE_APP_DIR "/data/vendor/sensor/chre"
|
|
#define CHRE_APP_DIR_PERMS (S_IRUSR | S_IWUSR | S_IXUSR)
|
|
#define CHRE_APP_FILE_PERMS (S_IRUSR | S_IWUSR)
|
|
#define CHRE_APP_SETTINGS CHRE_APP_DIR "/apps.json"
|
|
|
|
namespace android {
|
|
|
|
namespace nanohub {
|
|
|
|
static void readAppName(MessageBuf &buf, hub_app_name_t &name)
|
|
{
|
|
name.id = buf.readU64();
|
|
}
|
|
|
|
static void writeAppName(MessageBuf &buf, const hub_app_name_t &name)
|
|
{
|
|
buf.writeU64(name.id);
|
|
}
|
|
|
|
static void readNanohubMemInfo(MessageBuf &buf, NanohubMemInfo &mi)
|
|
{
|
|
uint8_t type, len;
|
|
uint32_t ramFree = NANOHUB_MEM_SZ_UNKNOWN;
|
|
uint32_t eeFree = NANOHUB_MEM_SZ_UNKNOWN;
|
|
uint32_t sharedFree = NANOHUB_MEM_SZ_UNKNOWN;
|
|
uint32_t osFree = NANOHUB_MEM_SZ_UNKNOWN;
|
|
|
|
mi.flashSz = NANOHUB_MEM_SZ_UNKNOWN;
|
|
mi.blSz = NANOHUB_MEM_SZ_UNKNOWN;
|
|
mi.osSz = NANOHUB_MEM_SZ_UNKNOWN;
|
|
mi.sharedSz = NANOHUB_MEM_SZ_UNKNOWN;
|
|
mi.eeSz = NANOHUB_MEM_SZ_UNKNOWN;
|
|
mi.ramSz = NANOHUB_MEM_SZ_UNKNOWN;
|
|
|
|
mi.blUse = NANOHUB_MEM_SZ_UNKNOWN;
|
|
mi.osUse = NANOHUB_MEM_SZ_UNKNOWN;
|
|
mi.sharedUse = NANOHUB_MEM_SZ_UNKNOWN;
|
|
mi.eeUse = NANOHUB_MEM_SZ_UNKNOWN;
|
|
mi.ramUse = NANOHUB_MEM_SZ_UNKNOWN;
|
|
|
|
while (buf.getRoom() >= 2) {
|
|
type = buf.readU8();
|
|
len = buf.readU8();
|
|
if (buf.getRoom() >= len) {
|
|
switch(type) {
|
|
case NANOHUB_HAL_SYS_INFO_HEAP_FREE:
|
|
if (len == sizeof(ramFree))
|
|
ramFree = buf.readU32();
|
|
else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_SYS_INFO_RAM_SIZE:
|
|
if (len == sizeof(mi.ramSz))
|
|
mi.ramSz = buf.readU32();
|
|
else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_SYS_INFO_EEDATA_SIZE:
|
|
if (len == sizeof(mi.ramSz))
|
|
mi.eeSz = buf.readU32();
|
|
else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_SYS_INFO_EEDATA_FREE:
|
|
if (len == sizeof(eeFree))
|
|
eeFree = buf.readU32();
|
|
else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_SYS_INFO_CODE_SIZE:
|
|
if (len == sizeof(mi.osSz))
|
|
mi.osSz = buf.readU32();
|
|
else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_SYS_INFO_CODE_FREE:
|
|
if (len == sizeof(osFree))
|
|
osFree = buf.readU32();
|
|
else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_SYS_INFO_SHARED_SIZE:
|
|
if (len == sizeof(mi.sharedSz))
|
|
mi.sharedSz = buf.readU32();
|
|
else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_SYS_INFO_SHARED_FREE:
|
|
if (len == sizeof(sharedFree))
|
|
sharedFree = buf.readU32();
|
|
else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_SYS_INFO_END:
|
|
if (len != 0 || buf.getRoom() != 0) {
|
|
ALOGE("%s: failed to read object", __func__);
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
ALOGI("%s: unsupported type: %d", __func__, type);
|
|
buf.readRaw(len);
|
|
break;
|
|
}
|
|
} else {
|
|
ALOGE("%s: failed to read object", __func__);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (buf.getRoom() != 0) {
|
|
ALOGE("%s: failed to read object", __func__);
|
|
return;
|
|
}
|
|
|
|
if (mi.ramSz != NANOHUB_MEM_SZ_UNKNOWN && ramFree != NANOHUB_MEM_SZ_UNKNOWN)
|
|
mi.ramUse = mi.ramSz - ramFree;
|
|
if (mi.eeSz != NANOHUB_MEM_SZ_UNKNOWN && eeFree != NANOHUB_MEM_SZ_UNKNOWN)
|
|
mi.eeUse = mi.eeSz - eeFree;
|
|
if (mi.osSz != NANOHUB_MEM_SZ_UNKNOWN && osFree != NANOHUB_MEM_SZ_UNKNOWN)
|
|
mi.osUse = mi.osSz - osFree;
|
|
if (mi.sharedSz != NANOHUB_MEM_SZ_UNKNOWN && sharedFree != NANOHUB_MEM_SZ_UNKNOWN)
|
|
mi.sharedUse = mi.sharedSz - sharedFree;
|
|
}
|
|
|
|
NanohubRsp::NanohubRsp(MessageBuf &buf, uint32_t transactionId, bool chre)
|
|
{
|
|
// all responses start with command and have a 4-byte status (result code)
|
|
buf.reset();
|
|
if (buf.getSize() < 5) {
|
|
mStatus = -EINVAL;
|
|
} else {
|
|
mCmd = buf.readU8();
|
|
mStatus = buf.readU32();
|
|
if (chre)
|
|
mTransactionId = transactionId;
|
|
else
|
|
mTransactionId = 0;
|
|
}
|
|
}
|
|
|
|
int SystemComm::sendToSystem(const void *data, size_t len, uint32_t transactionId)
|
|
{
|
|
if (NanoHub::messageTracingEnabled()) {
|
|
dumpBuffer("HAL -> SYS", getSystem()->mHostIfAppName, transactionId, 0, data, len);
|
|
}
|
|
return NanoHub::sendToDevice(&getSystem()->mHostIfAppName, data, len, transactionId);
|
|
}
|
|
|
|
inline hub_app_name_t deviceAppNameToHost(const hub_app_name_t src)
|
|
{
|
|
hub_app_name_t res = { .id = le64toh(src.id) };
|
|
return res;
|
|
}
|
|
|
|
inline hub_app_name_t hostAppNameToDevice(const hub_app_name_t src)
|
|
{
|
|
hub_app_name_t res = { .id = htole64(src.id) };
|
|
return res;
|
|
}
|
|
|
|
const uint8_t app_info_tags[] =
|
|
{
|
|
NANOHUB_HAL_APP_INFO_APPID,
|
|
NANOHUB_HAL_APP_INFO_CRC,
|
|
NANOHUB_HAL_APP_INFO_TID,
|
|
NANOHUB_HAL_APP_INFO_VERSION,
|
|
NANOHUB_HAL_APP_INFO_ADDR,
|
|
NANOHUB_HAL_APP_INFO_SIZE,
|
|
NANOHUB_HAL_APP_INFO_HEAP,
|
|
NANOHUB_HAL_APP_INFO_DATA,
|
|
NANOHUB_HAL_APP_INFO_BSS,
|
|
NANOHUB_HAL_APP_INFO_CHRE_MAJOR,
|
|
NANOHUB_HAL_APP_INFO_CHRE_MINOR,
|
|
NANOHUB_HAL_APP_INFO_END,
|
|
};
|
|
|
|
const uint8_t sys_info_tags[] =
|
|
{
|
|
NANOHUB_HAL_SYS_INFO_HEAP_FREE,
|
|
NANOHUB_HAL_SYS_INFO_RAM_SIZE,
|
|
NANOHUB_HAL_SYS_INFO_EEDATA_SIZE,
|
|
NANOHUB_HAL_SYS_INFO_EEDATA_FREE,
|
|
NANOHUB_HAL_SYS_INFO_CODE_SIZE,
|
|
NANOHUB_HAL_SYS_INFO_CODE_FREE,
|
|
NANOHUB_HAL_SYS_INFO_SHARED_SIZE,
|
|
NANOHUB_HAL_SYS_INFO_SHARED_FREE,
|
|
NANOHUB_HAL_SYS_INFO_END,
|
|
};
|
|
|
|
int SystemComm::MemInfoSession::setup(const hub_message_t *, uint32_t transactionId, AppManager &)
|
|
{
|
|
std::lock_guard<std::mutex> _l(mLock);
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
buf.writeU8(NANOHUB_HAL_SYS_INFO);
|
|
buf.writeRaw(sys_info_tags, sizeof(sys_info_tags));
|
|
|
|
setState(SESSION_USER);
|
|
return sendToSystem(buf.getData(), buf.getPos(), transactionId);
|
|
}
|
|
|
|
int SystemComm::MemInfoSession::handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &, bool chre)
|
|
{
|
|
std::lock_guard<std::mutex> _l(mLock);
|
|
NanohubRsp rsp(buf, transactionId, chre);
|
|
|
|
if (rsp.mCmd != NANOHUB_HAL_SYS_INFO)
|
|
return 1;
|
|
|
|
size_t len = buf.getRoom();
|
|
|
|
if (getState() != SESSION_USER) {
|
|
ALOGE("%s: Invalid state; have %d, need %d", __func__, getState(), SESSION_USER);
|
|
return -EINVAL;
|
|
}
|
|
|
|
std::vector<mem_range_t> ranges;
|
|
ranges.reserve(4);
|
|
if (len) {
|
|
NanohubMemInfo mi;
|
|
readNanohubMemInfo(buf, mi);
|
|
|
|
//if each is valid, copy to output area
|
|
if (mi.sharedSz != NANOHUB_MEM_SZ_UNKNOWN &&
|
|
mi.sharedUse != NANOHUB_MEM_SZ_UNKNOWN)
|
|
ranges.push_back({
|
|
.total_bytes = mi.sharedSz,
|
|
.free_bytes = mi.sharedSz - mi.sharedUse,
|
|
.type = HUB_MEM_TYPE_MAIN,
|
|
});
|
|
|
|
if (mi.osSz != NANOHUB_MEM_SZ_UNKNOWN &&
|
|
mi.osUse != NANOHUB_MEM_SZ_UNKNOWN)
|
|
ranges.push_back({
|
|
.total_bytes = mi.osSz,
|
|
.free_bytes = mi.osSz - mi.osUse,
|
|
.type = HUB_MEM_TYPE_OS,
|
|
});
|
|
|
|
if (mi.eeSz != NANOHUB_MEM_SZ_UNKNOWN &&
|
|
mi.eeUse != NANOHUB_MEM_SZ_UNKNOWN)
|
|
ranges.push_back({
|
|
.total_bytes = mi.eeSz,
|
|
.free_bytes = mi.eeSz - mi.eeUse,
|
|
.type = HUB_MEM_TYPE_EEDATA,
|
|
});
|
|
|
|
if (mi.ramSz != NANOHUB_MEM_SZ_UNKNOWN &&
|
|
mi.ramUse != NANOHUB_MEM_SZ_UNKNOWN)
|
|
ranges.push_back({
|
|
.total_bytes = mi.ramSz,
|
|
.free_bytes = mi.ramSz - mi.ramUse,
|
|
.type = HUB_MEM_TYPE_RAM,
|
|
});
|
|
}
|
|
|
|
//send it out
|
|
sendToApp(CONTEXT_HUB_QUERY_MEMORY, transactionId,
|
|
static_cast<const void *>(ranges.data()),
|
|
ranges.size() * sizeof(ranges[0]));
|
|
|
|
complete();
|
|
return 0;
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::setup(const hub_message_t *appMsg, uint32_t transactionId, AppManager &appManager)
|
|
{
|
|
std::lock_guard<std::mutex> _l(mLock);
|
|
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
const uint8_t *msgData = static_cast<const uint8_t*>(appMsg->message);
|
|
|
|
mCmd = appMsg->message_type;
|
|
mLen = appMsg->message_len;
|
|
mPos = 0;
|
|
mNextPos = 0;
|
|
mErrCnt = 0;
|
|
|
|
switch (mCmd) {
|
|
case CONTEXT_HUB_APPS_ENABLE:
|
|
return setupMgmt(appMsg, transactionId, NANOHUB_HAL_APP_MGMT_START, appManager);
|
|
case CONTEXT_HUB_APPS_DISABLE:
|
|
return setupMgmt(appMsg, transactionId, NANOHUB_HAL_APP_MGMT_STOP, appManager);
|
|
case CONTEXT_HUB_UNLOAD_APP:
|
|
return setupMgmt(appMsg, transactionId, NANOHUB_HAL_APP_MGMT_UNLOAD, appManager);
|
|
case CONTEXT_HUB_LOAD_APP:
|
|
{
|
|
const load_app_request_t *appReq = static_cast<const load_app_request_t*>(appMsg->message);
|
|
if (appReq == nullptr || mLen <= sizeof(*appReq)) {
|
|
ALOGE("%s: Invalid app header: too short\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
mAppName = appReq->app_binary.app_id;
|
|
if (!appManager.isAppLoaded(mAppName)) {
|
|
appManager.addNewApp(mAppName, appReq->app_binary.app_version);
|
|
appManager.writeApp(mAppName, msgData, mLen);
|
|
mData.clear();
|
|
mData = std::vector<uint8_t>(msgData, msgData + mLen);
|
|
setState(TRANSFER);
|
|
|
|
buf.writeU8(NANOHUB_HAL_START_UPLOAD);
|
|
buf.writeU8(0);
|
|
buf.writeU32(mLen);
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), transactionId);
|
|
} else {
|
|
if (appManager.cmpApp(mAppName, msgData, mLen)) {
|
|
mFlashAddr = appManager.getFlashAddr(mAppName);
|
|
if (appManager.isAppRunning(mAppName)) {
|
|
setState(STOP_RUN);
|
|
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT);
|
|
writeAppName(buf, mAppName);
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT_STOP);
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), transactionId);
|
|
} else {
|
|
setState(RUN);
|
|
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT);
|
|
writeAppName(buf, mAppName);
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT_START);
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), transactionId);
|
|
}
|
|
} else {
|
|
appManager.setCachedVersion(mAppName, appReq->app_binary.app_version);
|
|
appManager.writeApp(mAppName, msgData, mLen);
|
|
mData.clear();
|
|
mData = std::vector<uint8_t>(msgData, msgData + mLen);
|
|
if (appManager.isAppRunning(mAppName)) {
|
|
setState(STOP_TRANSFER);
|
|
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT);
|
|
writeAppName(buf, mAppName);
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT_STOP);
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), transactionId);
|
|
} else {
|
|
setState(TRANSFER);
|
|
|
|
buf.writeU8(NANOHUB_HAL_START_UPLOAD);
|
|
buf.writeU8(0);
|
|
buf.writeU32(mLen);
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), transactionId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
case CONTEXT_HUB_OS_REBOOT:
|
|
setState(REBOOT);
|
|
|
|
buf.writeU8(NANOHUB_HAL_SYS_MGMT);
|
|
buf.writeU8(NANOHUB_HAL_SYS_MGMT_REBOOT);
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), transactionId);
|
|
|
|
case CONTEXT_HUB_START_APPS:
|
|
if (mLen == sizeof(mStatus))
|
|
memcpy(&mStatus, msgData, mLen);
|
|
appManager.eraseApps();
|
|
setState(QUERY_START);
|
|
|
|
buf.writeU8(NANOHUB_HAL_APP_INFO);
|
|
buf.writeU32(0);
|
|
buf.writeRaw(app_info_tags, sizeof(app_info_tags));
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), transactionId);
|
|
}
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::setupMgmt(const hub_message_t *appMsg, uint32_t transactionId, uint32_t cmd, AppManager &appManager)
|
|
{
|
|
int32_t result = -1; // results are only directly returned on failure
|
|
const hub_app_name_t &appName = *static_cast<const hub_app_name_t*>(appMsg->message);
|
|
if (appMsg->message_len != sizeof(appName)) {
|
|
return -EINVAL;
|
|
}
|
|
mAppName = appName;
|
|
|
|
switch (cmd) {
|
|
case NANOHUB_HAL_APP_MGMT_START:
|
|
if (appManager.isAppRunning(mAppName)) {
|
|
appManager.setCachedStart(mAppName, true);
|
|
sendToApp(mCmd, transactionId, &result, sizeof(result));
|
|
complete();
|
|
return 0;
|
|
}
|
|
break;
|
|
case NANOHUB_HAL_APP_MGMT_STOP:
|
|
case NANOHUB_HAL_APP_MGMT_UNLOAD:
|
|
appManager.setCachedStart(mAppName, false);
|
|
if (!appManager.isAppRunning(mAppName)) {
|
|
sendToApp(mCmd, transactionId, &result, sizeof(result));
|
|
complete();
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT);
|
|
writeAppName(buf, appName);
|
|
buf.writeU8(cmd);
|
|
setState(MGMT);
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), transactionId);
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &appManager, bool chre)
|
|
{
|
|
int ret = 0;
|
|
std::lock_guard<std::mutex> _l(mLock);
|
|
NanohubRsp rsp(buf, transactionId, chre);
|
|
|
|
switch (getState()) {
|
|
case TRANSFER:
|
|
ret = handleTransfer(rsp, buf, appManager);
|
|
break;
|
|
case STOP_TRANSFER:
|
|
ret = handleStopTransfer(rsp, buf, appManager);
|
|
break;
|
|
case QUERY_START:
|
|
ret = handleQueryStart(rsp, buf, appManager);
|
|
break;
|
|
case START:
|
|
ret = handleStart(rsp, buf, appManager);
|
|
break;
|
|
case FINISH:
|
|
ret = handleFinish(rsp, buf, appManager);
|
|
break;
|
|
case RUN:
|
|
ret = handleRun(rsp, buf, appManager);
|
|
break;
|
|
case STOP_RUN:
|
|
ret = handleStopRun(rsp, buf, appManager);
|
|
break;
|
|
case REBOOT:
|
|
ret = handleReboot(rsp, buf, appManager);
|
|
break;
|
|
case ERASE_TRANSFER:
|
|
ret = handleEraseTransfer(rsp, buf, appManager);
|
|
break;
|
|
case MGMT:
|
|
ret = handleMgmt(rsp, buf, appManager);
|
|
break;
|
|
case INFO:
|
|
ret = handleInfo(rsp, buf, appManager);
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleTransfer(NanohubRsp &rsp, MessageBuf &, AppManager &appManager)
|
|
{
|
|
if (rsp.mCmd != NANOHUB_HAL_CONT_UPLOAD && rsp.mCmd != NANOHUB_HAL_START_UPLOAD)
|
|
return 1;
|
|
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
int32_t result = 0;
|
|
|
|
static_assert(NANOHUB_UPLOAD_CHUNK_SZ_MAX <= (MAX_RX_PACKET-5),
|
|
"Invalid chunk size");
|
|
|
|
if (rsp.mStatus == NANOHUB_HAL_UPLOAD_ACCEPTED) {
|
|
mPos = mNextPos;
|
|
mErrCnt = 0;
|
|
} else if (rsp.mStatus == NANOHUB_HAL_UPLOAD_RESEND) {
|
|
mErrCnt ++;
|
|
} else if (rsp.mStatus == NANOHUB_HAL_UPLOAD_RESTART) {
|
|
mPos = 0;
|
|
mErrCnt ++;
|
|
} else if (rsp.mStatus == NANOHUB_HAL_UPLOAD_CANCEL ||
|
|
rsp.mStatus == NANOHUB_HAL_UPLOAD_CANCEL_NO_RETRY) {
|
|
mPos = mLen;
|
|
result = NANOHUB_APP_NOT_LOADED;
|
|
} else if (rsp.mStatus == NANOHUB_HAL_UPLOAD_NO_SPACE) {
|
|
mPos = 0;
|
|
mErrCnt = 0;
|
|
setState(ERASE_TRANSFER);
|
|
|
|
buf.writeU8(NANOHUB_HAL_SYS_MGMT);
|
|
buf.writeU8(NANOHUB_HAL_SYS_MGMT_ERASE);
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId);
|
|
} else if (mErrCnt > 5) {
|
|
mPos = mLen;
|
|
result = NANOHUB_APP_NOT_LOADED;
|
|
} else {
|
|
mErrCnt ++;
|
|
}
|
|
|
|
if (result != 0) {
|
|
appManager.clearCachedApp(mAppName);
|
|
|
|
sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result));
|
|
complete();
|
|
return 0;
|
|
} else if (mPos < mLen) {
|
|
uint32_t chunkSize = mLen - mPos;
|
|
|
|
if (chunkSize > NANOHUB_UPLOAD_CHUNK_SZ_MAX) {
|
|
chunkSize = NANOHUB_UPLOAD_CHUNK_SZ_MAX;
|
|
}
|
|
|
|
buf.writeU8(NANOHUB_HAL_CONT_UPLOAD);
|
|
buf.writeU32(mPos);
|
|
buf.writeRaw(&mData[mPos], chunkSize);
|
|
mNextPos = mPos + chunkSize;
|
|
} else {
|
|
buf.writeU8(NANOHUB_HAL_FINISH_UPLOAD);
|
|
setState(FINISH);
|
|
}
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId);
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleStopTransfer(NanohubRsp &rsp, MessageBuf &buf, AppManager &)
|
|
{
|
|
if (rsp.mCmd != NANOHUB_HAL_APP_MGMT)
|
|
return 1;
|
|
|
|
uint8_t cmd = buf.readU8();
|
|
|
|
if (cmd != NANOHUB_HAL_APP_MGMT_STOP)
|
|
return 1;
|
|
|
|
MgmtStatus sts = { .value = buf.readU32() };
|
|
|
|
ALOGI("Nanohub NEW APP STOP: %08" PRIX32 "\n", sts.value);
|
|
if (rsp.mStatus == 0) {
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
setState(TRANSFER);
|
|
|
|
buf.writeU8(NANOHUB_HAL_START_UPLOAD);
|
|
buf.writeU8(0);
|
|
buf.writeU32(mLen);
|
|
return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId);
|
|
} else {
|
|
int32_t result = NANOHUB_APP_NOT_LOADED;
|
|
|
|
sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result));
|
|
complete();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleQueryStart(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager)
|
|
{
|
|
|
|
if (rsp.mCmd != NANOHUB_HAL_APP_INFO)
|
|
return 1;
|
|
|
|
size_t len = buf.getRoom();
|
|
if (len) {
|
|
uint32_t nextAddr = appManager.readNanohubAppInfo(buf);
|
|
|
|
if (nextAddr) {
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
|
|
buf.writeU8(NANOHUB_HAL_APP_INFO);
|
|
buf.writeU32(nextAddr);
|
|
buf.writeRaw(app_info_tags, sizeof(app_info_tags));
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId);
|
|
}
|
|
}
|
|
|
|
appManager.getAppsToStart(mAppList);
|
|
if (mAppList.empty()) {
|
|
sendToApp(CONTEXT_HUB_OS_REBOOT, 0, &mStatus, sizeof(mStatus));
|
|
complete();
|
|
return 0;
|
|
} else {
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
mAppName = mAppList.back();
|
|
mAppList.pop_back();
|
|
setState(START);
|
|
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT);
|
|
writeAppName(buf, mAppName);
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT_START);
|
|
return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId);
|
|
}
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleStart(NanohubRsp &rsp, MessageBuf &buf, AppManager &)
|
|
{
|
|
if (rsp.mCmd != NANOHUB_HAL_APP_MGMT)
|
|
return 1;
|
|
|
|
uint8_t cmd = buf.readU8();
|
|
|
|
if (cmd != NANOHUB_HAL_APP_MGMT_START)
|
|
return 1;
|
|
|
|
MgmtStatus sts = { .value = buf.readU32() };
|
|
|
|
ALOGI("Nanohub EXISTING APP START: %08" PRIX32 "\n", sts.value);
|
|
if (mAppList.empty()) {
|
|
sendToApp(CONTEXT_HUB_OS_REBOOT, 0, &mStatus, sizeof(mStatus));
|
|
complete();
|
|
return 0;
|
|
} else {
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
mAppName = mAppList.back();
|
|
mAppList.pop_back();
|
|
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT);
|
|
writeAppName(buf, mAppName);
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT_START);
|
|
return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId);
|
|
}
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleFinish(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager)
|
|
{
|
|
if (rsp.mCmd != NANOHUB_HAL_FINISH_UPLOAD)
|
|
return 1;
|
|
|
|
mFlashAddr = buf.readU32();
|
|
uint32_t crc = buf.readU32();
|
|
mData.clear();
|
|
|
|
if (rsp.mStatus == 0) {
|
|
appManager.setCachedCrc(mAppName, crc);
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
setState(RUN);
|
|
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT);
|
|
writeAppName(buf, mAppName);
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT_START);
|
|
return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId);
|
|
} else {
|
|
int32_t result = NANOHUB_APP_NOT_LOADED;
|
|
appManager.clearCachedApp(mAppName);
|
|
|
|
sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result));
|
|
complete();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleRun(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager)
|
|
{
|
|
if (rsp.mCmd != NANOHUB_HAL_APP_MGMT)
|
|
return 1;
|
|
|
|
uint8_t cmd = buf.readU8();
|
|
|
|
if (cmd != NANOHUB_HAL_APP_MGMT_START)
|
|
return 1;
|
|
|
|
MgmtStatus sts = { .value = buf.readU32() };
|
|
|
|
ALOGI("Nanohub NEW APP START: %08" PRIX32 "\n", sts.value);
|
|
if (rsp.mStatus == 0) {
|
|
appManager.setCachedStart(mAppName, true);
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
setState(INFO);
|
|
|
|
buf.writeU8(NANOHUB_HAL_APP_INFO);
|
|
buf.writeU32(mFlashAddr);
|
|
buf.writeRaw(app_info_tags, sizeof(app_info_tags));
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId);
|
|
} else {
|
|
appManager.setCachedStart(mAppName, false);
|
|
int32_t result = NANOHUB_APP_NOT_LOADED;
|
|
sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result));
|
|
complete();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleInfo(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager)
|
|
{
|
|
if (rsp.mCmd != NANOHUB_HAL_APP_INFO)
|
|
return 1;
|
|
int32_t result = 0;
|
|
size_t len = buf.getRoom();
|
|
if (len) {
|
|
appManager.readNanohubAppInfo(buf);
|
|
appManager.saveApps();
|
|
}
|
|
sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result));
|
|
complete();
|
|
return 0;
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleStopRun(NanohubRsp &rsp, MessageBuf &buf, AppManager &)
|
|
{
|
|
if (rsp.mCmd != NANOHUB_HAL_APP_MGMT)
|
|
return 1;
|
|
|
|
uint8_t cmd = buf.readU8();
|
|
|
|
if (cmd != NANOHUB_HAL_APP_MGMT_STOP)
|
|
return 1;
|
|
|
|
MgmtStatus sts = { .value = buf.readU32() };
|
|
|
|
ALOGI("Nanohub NEW APP STOP: %08" PRIX32 "\n", sts.value);
|
|
if (rsp.mStatus == 0) {
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
setState(RUN);
|
|
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT);
|
|
writeAppName(buf, mAppName);
|
|
buf.writeU8(NANOHUB_HAL_APP_MGMT_START);
|
|
return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId);
|
|
} else {
|
|
int32_t result = NANOHUB_APP_NOT_LOADED;
|
|
|
|
sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result));
|
|
complete();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* reboot notification, when triggered by App request */
|
|
int SystemComm::AppMgmtSession::handleReboot(NanohubRsp &rsp, MessageBuf &buf, AppManager &)
|
|
{
|
|
if (rsp.mCmd != NANOHUB_HAL_SYS_MGMT)
|
|
return 1;
|
|
|
|
uint8_t cmd = buf.readU8();
|
|
|
|
if (cmd == NANOHUB_HAL_SYS_MGMT_REBOOT)
|
|
ALOGI("Nanohub reboot status [USER REQ]: %08" PRIX32 "\n", rsp.mStatus);
|
|
|
|
// reboot notification is sent by SessionManager
|
|
complete();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleEraseTransfer(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager)
|
|
{
|
|
if (rsp.mCmd != NANOHUB_HAL_SYS_MGMT)
|
|
return 1;
|
|
|
|
uint8_t cmd = buf.readU8();
|
|
|
|
if (cmd == NANOHUB_HAL_SYS_MGMT_ERASE && rsp.mStatus == 0) {
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
appManager.eraseApps();
|
|
setState(TRANSFER);
|
|
|
|
buf.writeU8(NANOHUB_HAL_START_UPLOAD);
|
|
buf.writeU8(0);
|
|
buf.writeU32(mLen);
|
|
return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId);
|
|
} else {
|
|
int32_t result = NANOHUB_APP_NOT_LOADED;
|
|
|
|
sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result));
|
|
complete();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleMgmt(NanohubRsp &rsp, MessageBuf &buf, AppManager &appManager)
|
|
{
|
|
if (rsp.mCmd != NANOHUB_HAL_APP_MGMT)
|
|
return 1;
|
|
|
|
uint8_t cmd = buf.readU8();
|
|
MgmtStatus sts = { .value = buf.readU32() };
|
|
|
|
bool valid = false;
|
|
|
|
int32_t result = rsp.mStatus;
|
|
|
|
if (result != 0)
|
|
result = -1;
|
|
|
|
switch (cmd) {
|
|
case NANOHUB_HAL_APP_MGMT_STOP:
|
|
valid = mCmd == CONTEXT_HUB_APPS_DISABLE;
|
|
if (valid && rsp.mStatus == 0)
|
|
appManager.clearRunning(mAppName);
|
|
break;
|
|
case NANOHUB_HAL_APP_MGMT_START:
|
|
valid = mCmd == CONTEXT_HUB_APPS_ENABLE;
|
|
if (valid && rsp.mStatus == 0) {
|
|
appManager.setCachedStart(mAppName, true);
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
setState(INFO);
|
|
|
|
buf.writeU8(NANOHUB_HAL_APP_INFO);
|
|
buf.writeU32(appManager.getFlashAddr(mAppName));
|
|
buf.writeRaw(app_info_tags, sizeof(app_info_tags));
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), rsp.mTransactionId);
|
|
}
|
|
break;
|
|
case NANOHUB_HAL_APP_MGMT_UNLOAD:
|
|
valid = mCmd == CONTEXT_HUB_UNLOAD_APP;
|
|
if (valid && rsp.mStatus == 0)
|
|
appManager.clearRunning(mAppName);
|
|
break;
|
|
default:
|
|
return 1;
|
|
}
|
|
|
|
ALOGI("Nanohub MGMT response: CMD=%02X; STATUS=%08" PRIX32, rsp.mCmd, sts.value);
|
|
if (!valid) {
|
|
ALOGE("Invalid response for this state: APP CMD=%02X", mCmd);
|
|
return -EINVAL;
|
|
}
|
|
|
|
sendToApp(mCmd, rsp.mTransactionId, &result, sizeof(result));
|
|
complete();
|
|
return 0;
|
|
}
|
|
|
|
int SystemComm::KeyInfoSession::setup(const hub_message_t *, uint32_t transactionId, AppManager &) {
|
|
std::lock_guard<std::mutex> _l(mLock);
|
|
mKeyNum = 0;
|
|
mKeyOffset = 0;
|
|
mRsaKeyData.clear();
|
|
setState(SESSION_USER);
|
|
mStatus = -EBUSY;
|
|
return requestRsaKeys(transactionId);
|
|
}
|
|
|
|
int SystemComm::KeyInfoSession::handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &, bool chre)
|
|
{
|
|
std::lock_guard<std::mutex> _l(mLock);
|
|
NanohubRsp rsp(buf, transactionId, chre);
|
|
|
|
if (getState() != SESSION_USER) {
|
|
// invalid state
|
|
mStatus = -EFAULT;
|
|
return mStatus;
|
|
}
|
|
|
|
uint32_t keyLen = buf.readU32();
|
|
uint32_t dataLen = buf.getRoom();
|
|
|
|
if (dataLen) {
|
|
mRsaKeyData.insert(mRsaKeyData.end(),
|
|
buf.getData() + buf.getPos(),
|
|
buf.getData() + buf.getSize());
|
|
if (mKeyOffset + dataLen >= keyLen) {
|
|
mKeyNum++;
|
|
mKeyOffset = 0;
|
|
} else {
|
|
mKeyOffset += dataLen;
|
|
}
|
|
return requestRsaKeys(transactionId);
|
|
} else {
|
|
mStatus = 0;
|
|
complete();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int SystemComm::KeyInfoSession::requestRsaKeys(uint32_t transactionId)
|
|
{
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
|
|
buf.writeU8(NANOHUB_HAL_KEY_INFO);
|
|
buf.writeU32(mKeyNum);
|
|
buf.writeU32(mKeyOffset);
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos(), transactionId);
|
|
}
|
|
|
|
void SystemComm::AppManager::dumpAppInfo(std::string &result)
|
|
{
|
|
char buffer[256];
|
|
|
|
for (auto &it : apps_) {
|
|
uint64_t id = it.first;
|
|
const auto &app = it.second;
|
|
|
|
snprintf(buffer, sizeof(buffer), "App: 0x%016" PRIx64 "\n", id);
|
|
result.append(buffer);
|
|
if (app->loaded) {
|
|
snprintf(buffer, sizeof(buffer),
|
|
" Version: 0x%08" PRIx32 "\n"
|
|
" flashAddr: 0x%08" PRIx32 "\n"
|
|
" Running: %s\n",
|
|
app->version,
|
|
app->flashAddr,
|
|
app->running ? "true" : "false");
|
|
result.append(buffer);
|
|
|
|
if (app->flashUse != NANOHUB_MEM_SZ_UNKNOWN) {
|
|
snprintf(buffer, sizeof(buffer),
|
|
" flashUse: %d\n"
|
|
" CRC: 0x%08" PRIx32 "\n",
|
|
app->flashUse,
|
|
app->crc);
|
|
result.append(buffer);
|
|
}
|
|
|
|
if (app->running) {
|
|
snprintf(buffer, sizeof(buffer),
|
|
" TID: %04x\n"
|
|
" ramUse: %d\n",
|
|
app->tid,
|
|
app->ramUse);
|
|
result.append(buffer);
|
|
}
|
|
|
|
if (app->chre) {
|
|
snprintf(buffer, sizeof(buffer), " CHRE: %d.%d\n",
|
|
app->chre_major, app->chre_minor);
|
|
result.append(buffer);
|
|
}
|
|
}
|
|
|
|
if (app->cached_napp) {
|
|
snprintf(buffer, sizeof(buffer),
|
|
" Cached Version: 0x%08" PRIx32 "\n"
|
|
" Cached Start: %s\n"
|
|
" Cached CRC: 0x%08" PRIx32 "\n",
|
|
app->cached_version,
|
|
app->cached_start ? "true" : "false",
|
|
app->cached_crc);
|
|
result.append(buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SystemComm::AppManager::saveApps()
|
|
{
|
|
mkdir(CHRE_APP_DIR, CHRE_APP_DIR_PERMS);
|
|
File saved_apps_file(CHRE_APP_SETTINGS, "w");
|
|
std::shared_ptr<Json::Value> appsObject(new Json::Value);
|
|
status_t err;
|
|
|
|
if ((err = saved_apps_file.initCheck()) != OK) {
|
|
ALOGW("saved_apps file open (w) failed %d (%s)",
|
|
err,
|
|
strerror(-err));
|
|
return false;
|
|
}
|
|
|
|
for (auto &it : apps_) {
|
|
uint64_t id = it.first;
|
|
const auto &app = it.second;
|
|
|
|
if (app->cached_napp) {
|
|
char hexId[17];
|
|
snprintf(hexId, sizeof(hexId), "%016" PRIX64, id);
|
|
Json::Value array(Json::arrayValue);
|
|
array[0] = app->cached_version;
|
|
array[1] = app->cached_start;
|
|
array[2] = app->cached_crc;
|
|
(*appsObject)[hexId] = array;
|
|
}
|
|
}
|
|
|
|
// Write the JSON string to disk.
|
|
Json::StreamWriterBuilder factory;
|
|
std::string serializedSettings(Json::writeString(factory, *appsObject));
|
|
size_t size = serializedSettings.size();
|
|
if ((err = saved_apps_file.write(serializedSettings.c_str(), size)) != (ssize_t)size) {
|
|
ALOGW("saved_apps file write failed %d (%s)",
|
|
err,
|
|
strerror(-err));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SystemComm::AppManager::restoreApps()
|
|
{
|
|
File saved_apps_file(CHRE_APP_SETTINGS, "r");
|
|
std::shared_ptr<Json::Value> appsObject;
|
|
status_t err;
|
|
|
|
if ((err = saved_apps_file.initCheck()) != OK) {
|
|
ALOGW("saved_apps file open (r) failed %d (%s)",
|
|
err,
|
|
strerror(-err));
|
|
return false;
|
|
}
|
|
|
|
off64_t size = saved_apps_file.seekTo(0, SEEK_END);
|
|
saved_apps_file.seekTo(0, SEEK_SET);
|
|
|
|
if (size > 0) {
|
|
char *buf = (char *)malloc(size);
|
|
CHECK_EQ(saved_apps_file.read(buf, size), (ssize_t)size);
|
|
|
|
std::string str(buf);
|
|
std::shared_ptr<Json::Value> in(new Json::Value);
|
|
Json::CharReaderBuilder builder;
|
|
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
|
bool valid = reader->parse(
|
|
str.data(), str.data() + str.size(), in.get(), /* errorMessage = */ nullptr);
|
|
free(buf);
|
|
|
|
if (valid && in->isObject()) {
|
|
appsObject = in;
|
|
}
|
|
}
|
|
|
|
if (appsObject == nullptr) {
|
|
appsObject = std::shared_ptr<Json::Value>(new Json::Value(Json::objectValue));
|
|
}
|
|
|
|
Json::Value::Members apps = appsObject->getMemberNames();
|
|
for (auto &it : apps) {
|
|
Json::Value &val = (*appsObject)[it];
|
|
if (val.isArray()) {
|
|
uint32_t version = val[0].asUInt();
|
|
uint32_t start = val[1].asUInt();
|
|
uint32_t crc = val[2].asUInt();
|
|
|
|
uint64_t id = strtoull(it.c_str(), nullptr, 16);
|
|
apps_[id] = std::unique_ptr<AppData>(new AppData);
|
|
apps_[id]->loaded = false;
|
|
apps_[id]->running = false;
|
|
apps_[id]->chre = false;
|
|
apps_[id]->cached_napp = true;
|
|
apps_[id]->cached_version = version;
|
|
apps_[id]->cached_start = start;
|
|
apps_[id]->cached_crc = crc;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SystemComm::AppManager::eraseApps()
|
|
{
|
|
for (auto it=apps_.begin(); it != apps_.end();) {
|
|
if (!it->second->cached_napp)
|
|
it = apps_.erase(it);
|
|
else {
|
|
it->second->loaded = false;
|
|
it->second->running = false;
|
|
it->second->chre = false;
|
|
++it;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SystemComm::AppManager::writeApp(hub_app_name_t &appName, const uint8_t *data, int32_t len)
|
|
{
|
|
mkdir(CHRE_APP_DIR, CHRE_APP_DIR_PERMS);
|
|
char file[strlen(CHRE_APP_DIR) + strlen("/") + 16 + strlen(".napp") + 1];
|
|
|
|
snprintf(file, sizeof(file), "%s/%016" PRIX64 ".napp", CHRE_APP_DIR, appName.id);
|
|
|
|
int fd = open(file, O_CREAT | O_WRONLY | O_TRUNC, CHRE_APP_FILE_PERMS);
|
|
if (fd == -1)
|
|
return false;
|
|
|
|
if (write(fd, data, len) == len) {
|
|
close(fd);
|
|
return true;
|
|
} else {
|
|
close(fd);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
int32_t SystemComm::AppManager::readApp(hub_app_name_t &appName, void **data)
|
|
{
|
|
char file[strlen(CHRE_APP_DIR) + strlen("/") + 16 + strlen(".napp") + 1];
|
|
|
|
snprintf(file, sizeof(file), "%s/%016" PRIX64 ".napp", CHRE_APP_DIR, appName.id);
|
|
|
|
int32_t ret = -1;
|
|
*data = nullptr;
|
|
int fd = open(file, O_RDONLY);
|
|
|
|
if (fd >= 0) {
|
|
struct stat sb;
|
|
if (fstat(fd, &sb) == 0) {
|
|
*data = malloc(sb.st_size);
|
|
if (*data != nullptr && read(fd, *data, sb.st_size) == sb.st_size)
|
|
ret = sb.st_size;
|
|
else {
|
|
free(*data);
|
|
*data = nullptr;
|
|
}
|
|
}
|
|
close(fd);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool SystemComm::AppManager::cmpApp(hub_app_name_t &appName, const uint8_t *data, uint32_t len)
|
|
{
|
|
char file[strlen(CHRE_APP_DIR) + strlen("/") + 16 + strlen(".napp") + 1];
|
|
|
|
snprintf(file, sizeof(file), "%s/%016" PRIX64 ".napp", CHRE_APP_DIR, appName.id);
|
|
|
|
if (!isAppLoaded(appName))
|
|
return false;
|
|
|
|
if ((!apps_[appName.id]->cached_napp) ||
|
|
(apps_[appName.id]->crc != apps_[appName.id]->cached_crc))
|
|
return false;
|
|
|
|
bool success = false;
|
|
int fd = open(file, O_RDONLY);
|
|
|
|
if (fd >= 0) {
|
|
struct stat sb;
|
|
if (fstat(fd, &sb) == 0 && sb.st_size == len) {
|
|
void *buf = malloc(len);
|
|
if (buf != nullptr && read(fd, buf, sb.st_size) == sb.st_size && memcmp(data, buf, len) == 0)
|
|
success = true;
|
|
free(buf);
|
|
}
|
|
close(fd);
|
|
}
|
|
return success;
|
|
}
|
|
|
|
uint32_t SystemComm::AppManager::readNanohubAppInfo(MessageBuf &buf)
|
|
{
|
|
hub_app_name_t name;
|
|
|
|
uint8_t tag, len;
|
|
uint32_t ramUse = 0;
|
|
bool ramUseValid = true;
|
|
|
|
// first tag must be the appid
|
|
if (buf.getRoom() < 2 + sizeof(name.id)) {
|
|
ALOGE("%s: failed to read object", __func__);
|
|
return 0;
|
|
}
|
|
|
|
tag = buf.readU8();
|
|
len = buf.readU8();
|
|
if (tag != NANOHUB_HAL_APP_INFO_APPID || len != sizeof(name.id)) {
|
|
ALOGE("%s: invalid first tag: %d", __func__, tag);
|
|
return 0;
|
|
}
|
|
|
|
readAppName(buf, name);
|
|
if (!isAppPresent(name)) {
|
|
apps_[name.id] = std::unique_ptr<AppData>(new AppData);
|
|
apps_[name.id]->loaded = false;
|
|
apps_[name.id]->chre = false;
|
|
apps_[name.id]->running = false;
|
|
apps_[name.id]->cached_napp = false;
|
|
}
|
|
const auto &app = apps_[name.id];
|
|
|
|
while (buf.getRoom() >= 2) {
|
|
tag = buf.readU8();
|
|
len = buf.readU8();
|
|
if (buf.getRoom() >= len) {
|
|
switch(tag) {
|
|
case NANOHUB_HAL_APP_INFO_CRC:
|
|
if (len == 0)
|
|
app->crc = 0;
|
|
else if (len == sizeof(app->crc))
|
|
app->crc = buf.readU32();
|
|
else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_APP_INFO_TID:
|
|
if (len == 0) {
|
|
app->tid = NANOHUB_TID_UNKNOWN;
|
|
ramUseValid = false;
|
|
app->loaded = true;
|
|
app->running = false;
|
|
} else if (len == sizeof(app->tid)) {
|
|
app->tid = buf.readU32();
|
|
app->loaded = true;
|
|
app->running = true;
|
|
} else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_APP_INFO_VERSION:
|
|
if (len == sizeof(app->version))
|
|
app->version = buf.readU32();
|
|
else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_APP_INFO_ADDR:
|
|
if (len == sizeof(app->flashAddr))
|
|
app->flashAddr = buf.readU32();
|
|
else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_APP_INFO_SIZE:
|
|
if (len == 0)
|
|
app->flashUse = NANOHUB_MEM_SZ_UNKNOWN;
|
|
else if (len == sizeof(app->flashUse))
|
|
app->flashUse = buf.readU32();
|
|
else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_APP_INFO_HEAP:
|
|
case NANOHUB_HAL_APP_INFO_DATA:
|
|
case NANOHUB_HAL_APP_INFO_BSS:
|
|
if (len == 0)
|
|
ramUseValid = false;
|
|
else if (len == sizeof(uint32_t))
|
|
ramUse += buf.readU32();
|
|
else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_APP_INFO_CHRE_MAJOR:
|
|
if (len == 0)
|
|
app->chre = false;
|
|
else if (len == sizeof(app->chre_major)) {
|
|
app->chre = true;
|
|
app->chre_major = buf.readU8();
|
|
} else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_APP_INFO_CHRE_MINOR:
|
|
if (len == 0)
|
|
app->chre = false;
|
|
else if (len == sizeof(app->chre_minor)) {
|
|
app->chre = true;
|
|
app->chre_minor = buf.readU8();
|
|
} else
|
|
buf.readRaw(len);
|
|
break;
|
|
case NANOHUB_HAL_APP_INFO_END:
|
|
if (len != 0 || buf.getRoom() != 0) {
|
|
ALOGE("%s: failed to read object", __func__);
|
|
return 0;
|
|
}
|
|
break;
|
|
default:
|
|
ALOGI("%s: unsupported tag: %d", __func__, tag);
|
|
buf.readRaw(len);
|
|
break;
|
|
}
|
|
} else {
|
|
ALOGE("%s: failed to read object", __func__);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (buf.getRoom() != 0) {
|
|
ALOGE("%s: failed to read object", __func__);
|
|
return 0;
|
|
}
|
|
|
|
if (ramUseValid)
|
|
app->ramUse = ramUse;
|
|
else
|
|
app->ramUse = NANOHUB_MEM_SZ_UNKNOWN;
|
|
|
|
return app->flashAddr +
|
|
(app->flashUse != NANOHUB_MEM_SZ_UNKNOWN ? ((app->flashUse+3)&~3) : 4);
|
|
}
|
|
|
|
void SystemComm::AppManager::sendAppInfoToApp(uint32_t transactionId) {
|
|
std::vector<hub_app_info> appInfo;
|
|
for (auto &it : apps_) {
|
|
uint64_t id = it.first;
|
|
const auto &app = it.second;
|
|
|
|
// TODO: Still have some non-chre apps that need to be reported
|
|
// if (!app->chre || !app->running || app->flashUse == NANOHUB_MEM_SZ_UNKNOWN)
|
|
if (!app->running || app->flashUse == NANOHUB_MEM_SZ_UNKNOWN)
|
|
continue;
|
|
|
|
hub_app_info info;
|
|
info.app_name = { .id = id };
|
|
info.version = app->version;
|
|
info.num_mem_ranges = 0;
|
|
if (app->flashUse != NANOHUB_MEM_SZ_UNKNOWN) {
|
|
mem_range_t &range = info.mem_usage[info.num_mem_ranges++];
|
|
range.type = HUB_MEM_TYPE_MAIN;
|
|
range.total_bytes = app->flashUse;
|
|
}
|
|
if (app->ramUse != NANOHUB_MEM_SZ_UNKNOWN) {
|
|
mem_range_t &range = info.mem_usage[info.num_mem_ranges++];
|
|
range.type = HUB_MEM_TYPE_RAM;
|
|
range.total_bytes = app->ramUse;
|
|
}
|
|
|
|
appInfo.push_back(info);
|
|
}
|
|
sendToApp(CONTEXT_HUB_QUERY_APPS, transactionId,
|
|
static_cast<const void *>(appInfo.data()),
|
|
appInfo.size() * sizeof(appInfo[0]));
|
|
}
|
|
|
|
int SystemComm::AppManager::getAppsToStart(std::vector<hub_app_name_t> &apps)
|
|
{
|
|
int cnt = 0;
|
|
apps.clear();
|
|
|
|
for (auto &it : apps_) {
|
|
uint64_t id = it.first;
|
|
const auto &app = it.second;
|
|
|
|
if (app->cached_napp && app->cached_start && app->loaded &&
|
|
!app->running && app->flashUse != NANOHUB_MEM_SZ_UNKNOWN) {
|
|
apps.push_back({ .id = id });
|
|
cnt++;
|
|
}
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
int SystemComm::doHandleRx(uint64_t appId, uint32_t transactionId, const char *data, int len, bool chre)
|
|
{
|
|
bool reboot = false;
|
|
uint32_t rebootStatus;
|
|
//we only care for messages from HostIF
|
|
if (appId != mHostIfAppName.id)
|
|
return 1;
|
|
|
|
//they must all be at least 1 byte long
|
|
if (!len) {
|
|
return -EINVAL;
|
|
}
|
|
MessageBuf buf(data, len);
|
|
if (NanoHub::messageTracingEnabled()) {
|
|
dumpBuffer("SYS -> HAL", mHostIfAppName, transactionId, 0, buf.getData(), buf.getSize());
|
|
}
|
|
int status = mSessions.handleRx(buf, transactionId, mAppManager, chre, reboot, rebootStatus);
|
|
if (status) {
|
|
// provide default handler for any system message, that is not properly handled
|
|
dumpBuffer(status > 0 ? "HAL (not handled)" : "HAL (error)",
|
|
mHostIfAppName, transactionId, 0, buf.getData(), buf.getSize(), status);
|
|
status = status > 0 ? 0 : status;
|
|
}
|
|
if (reboot) {
|
|
hub_message_t msg =
|
|
{
|
|
.app_name.id = appId,
|
|
.message_type = CONTEXT_HUB_START_APPS,
|
|
.message_len = sizeof(rebootStatus),
|
|
.message = &rebootStatus,
|
|
};
|
|
|
|
status = doHandleTx(&msg, 0xFFFFFFFF);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
void SystemComm::doDumpAppInfo(std::string &result)
|
|
{
|
|
mAppManager.dumpAppInfo(result);
|
|
}
|
|
|
|
int SystemComm::SessionManager::handleRx(MessageBuf &buf, uint32_t transactionId, AppManager &appManager, bool chre, bool &reboot, uint32_t &rebootStatus)
|
|
{
|
|
int status = 1;
|
|
std::unique_lock<std::mutex> lk(lock);
|
|
|
|
// pass message to all active sessions, in arbitrary order
|
|
// 1st session that handles the message terminates the loop
|
|
for (auto pos = sessions_.begin(); pos != sessions_.end() && status > 0; next(pos)) {
|
|
if (!isActive(pos)) {
|
|
continue;
|
|
}
|
|
Session *session = pos->second;
|
|
status = session->handleRx(buf, transactionId, appManager, chre);
|
|
if (status < 0) {
|
|
session->complete();
|
|
}
|
|
}
|
|
|
|
NanohubRsp rsp(buf, transactionId, chre);
|
|
if (rsp.mCmd == NANOHUB_HAL_SYS_MGMT) {
|
|
uint8_t cmd = buf.readU8();
|
|
|
|
if (cmd == NANOHUB_HAL_SYS_MGMT_REBOOT) {
|
|
// if this is reboot notification, kill all sessions
|
|
for (auto pos = sessions_.begin(); pos != sessions_.end(); next(pos)) {
|
|
if (!isActive(pos)) {
|
|
continue;
|
|
}
|
|
Session *session = pos->second;
|
|
session->abort(-EINTR);
|
|
}
|
|
lk.unlock();
|
|
// log the reboot event, if not handled
|
|
if (status > 0) {
|
|
ALOGW("Nanohub reboot status [UNSOLICITED]: %08" PRIX32, rsp.mStatus);
|
|
status = 0;
|
|
}
|
|
reboot = true;
|
|
rebootStatus = rsp.mStatus;
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
int SystemComm::SessionManager::setup_and_add(int id, Session *session, const hub_message_t *appMsg, uint32_t transactionId, AppManager &appManager)
|
|
{
|
|
std::lock_guard<std::mutex> _l(lock);
|
|
|
|
// scan sessions to release those that are already done
|
|
for (auto pos = sessions_.begin(); pos != sessions_.end(); next(pos)) {
|
|
continue;
|
|
}
|
|
|
|
if (sessions_.count(id) == 0 && !session->isRunning()) {
|
|
sessions_[id] = session;
|
|
int ret = session->setup(appMsg, transactionId, appManager);
|
|
if (ret < 0) {
|
|
session->complete();
|
|
}
|
|
return ret;
|
|
}
|
|
return -EBUSY;
|
|
}
|
|
|
|
int SystemComm::doHandleTx(const hub_message_t *appMsg, uint32_t transactionId)
|
|
{
|
|
int status = 0;
|
|
|
|
switch (appMsg->message_type) {
|
|
case CONTEXT_HUB_LOAD_APP:
|
|
if (!mKeySession.haveKeys()) {
|
|
status = mSessions.setup_and_add(CONTEXT_HUB_LOAD_APP, &mKeySession, appMsg, transactionId, mAppManager);
|
|
if (status < 0) {
|
|
break;
|
|
}
|
|
mKeySession.wait();
|
|
status = mKeySession.getStatus();
|
|
if (status < 0) {
|
|
break;
|
|
}
|
|
}
|
|
status = mSessions.setup_and_add(CONTEXT_HUB_LOAD_APP, &mAppMgmtSession, appMsg, transactionId, mAppManager);
|
|
break;
|
|
case CONTEXT_HUB_APPS_ENABLE:
|
|
case CONTEXT_HUB_APPS_DISABLE:
|
|
case CONTEXT_HUB_UNLOAD_APP:
|
|
// all APP-modifying commands share session key, to ensure they can't happen at the same time
|
|
status = mSessions.setup_and_add(CONTEXT_HUB_LOAD_APP, &mAppMgmtSession, appMsg, transactionId, mAppManager);
|
|
break;
|
|
|
|
case CONTEXT_HUB_QUERY_APPS:
|
|
mAppManager.sendAppInfoToApp(transactionId);
|
|
break;
|
|
|
|
case CONTEXT_HUB_QUERY_MEMORY:
|
|
status = mSessions.setup_and_add(CONTEXT_HUB_QUERY_MEMORY, &mMemInfoSession, appMsg, transactionId, mAppManager);
|
|
break;
|
|
|
|
case CONTEXT_HUB_START_APPS:
|
|
status = mSessions.setup_and_add(CONTEXT_HUB_START_APPS, &mAppMgmtSession, appMsg, transactionId, mAppManager);
|
|
break;
|
|
|
|
default:
|
|
ALOGW("Unknown os message type %u\n", appMsg->message_type);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
}; // namespace nanohub
|
|
|
|
}; // namespace android
|