686 lines
19 KiB
C++
686 lines
19 KiB
C++
/*
|
|
* 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 <cassert>
|
|
#include <cerrno>
|
|
#include <cinttypes>
|
|
|
|
#include <endian.h>
|
|
|
|
#include <vector>
|
|
|
|
#include <log/log.h>
|
|
|
|
#include <endian.h>
|
|
|
|
#include <hardware/context_hub.h>
|
|
#include "nanohub_perdevice.h"
|
|
#include "system_comms.h"
|
|
#include "nanohubhal.h"
|
|
|
|
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 readNanohubAppInfo(MessageBuf &buf, NanohubAppInfo &info)
|
|
{
|
|
size_t pos = buf.getPos();
|
|
readAppName(buf, info.name);
|
|
info.version = buf.readU32();
|
|
info.flashUse = buf.readU32();
|
|
info.ramUse = buf.readU32();
|
|
if ((buf.getPos() - pos) != sizeof(info)) {
|
|
ALOGE("%s: failed to read object", __func__);
|
|
}
|
|
}
|
|
|
|
static void readNanohubMemInfo(MessageBuf &buf, NanohubMemInfo &mi)
|
|
{
|
|
size_t pos = buf.getPos();
|
|
mi.flashSz = buf.readU32();
|
|
mi.blSz = buf.readU32();
|
|
mi.osSz = buf.readU32();
|
|
mi.sharedSz = buf.readU32();
|
|
mi.eeSz = buf.readU32();
|
|
mi.ramSz = buf.readU32();
|
|
|
|
mi.blUse = buf.readU32();
|
|
mi.osUse = buf.readU32();
|
|
mi.sharedUse = buf.readU32();
|
|
mi.eeUse = buf.readU32();
|
|
mi.ramUse = buf.readU32();
|
|
if ((buf.getPos() - pos) != sizeof(mi)) {
|
|
ALOGE("%s: failed to read object", __func__);
|
|
}
|
|
}
|
|
|
|
NanohubRsp::NanohubRsp(MessageBuf &buf, bool no_status)
|
|
{
|
|
// all responses start with command
|
|
// most of them have 4-byte status (result code)
|
|
buf.reset();
|
|
cmd = buf.readU8();
|
|
if (!buf.getSize()) {
|
|
status = -EINVAL;
|
|
} else if (no_status) {
|
|
status = 0;
|
|
} else {
|
|
status = buf.readU32();
|
|
}
|
|
}
|
|
|
|
int SystemComm::sendToSystem(const void *data, size_t len)
|
|
{
|
|
if (NanoHub::messageTracingEnabled()) {
|
|
dumpBuffer("HAL -> SYS", getSystem()->mHostIfAppName, 0, data, len);
|
|
}
|
|
return NanoHub::sendToDevice(&getSystem()->mHostIfAppName, data, len);
|
|
}
|
|
|
|
int SystemComm::AppInfoSession::setup(const hub_message_t *)
|
|
{
|
|
std::lock_guard<std::mutex> _l(mLock);
|
|
int suggestedSize = mAppInfo.size() ? mAppInfo.size() : 20;
|
|
|
|
mAppInfo.clear();
|
|
mAppInfo.reserve(suggestedSize);
|
|
setState(SESSION_USER);
|
|
|
|
return requestNext();
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
int SystemComm::AppInfoSession::handleRx(MessageBuf &buf)
|
|
{
|
|
std::lock_guard<std::mutex> _l(mLock);
|
|
|
|
NanohubRsp rsp(buf, true);
|
|
if (rsp.cmd != NANOHUB_QUERY_APPS) {
|
|
return 1;
|
|
}
|
|
size_t len = buf.getRoom();
|
|
if (len != sizeof(NanohubAppInfo) && len) {
|
|
ALOGE("%s: Invalid data size; have %zu, need %zu", __func__,
|
|
len, sizeof(NanohubAppInfo));
|
|
return -EINVAL;
|
|
}
|
|
if (getState() != SESSION_USER) {
|
|
ALOGE("%s: Invalid state; have %d, need %d", __func__, getState(), SESSION_USER);
|
|
return -EINVAL;
|
|
}
|
|
if (len) {
|
|
NanohubAppInfo info;
|
|
readNanohubAppInfo(buf, info);
|
|
hub_app_info appInfo;
|
|
appInfo.num_mem_ranges = 0;
|
|
if (info.flashUse != NANOHUB_MEM_SZ_UNKNOWN) {
|
|
mem_range_t &range = appInfo.mem_usage[appInfo.num_mem_ranges++];
|
|
range.type = HUB_MEM_TYPE_MAIN;
|
|
range.total_bytes = info.flashUse;
|
|
}
|
|
if (info.ramUse != NANOHUB_MEM_SZ_UNKNOWN) {
|
|
mem_range_t &range = appInfo.mem_usage[appInfo.num_mem_ranges++];
|
|
range.type = HUB_MEM_TYPE_RAM;
|
|
range.total_bytes = info.ramUse;
|
|
}
|
|
|
|
appInfo.app_name = info.name;
|
|
appInfo.version = info.version;
|
|
|
|
mAppInfo.push_back(appInfo);
|
|
return requestNext();
|
|
} else {
|
|
sendToApp(CONTEXT_HUB_QUERY_APPS,
|
|
static_cast<const void *>(mAppInfo.data()),
|
|
mAppInfo.size() * sizeof(mAppInfo[0]));
|
|
complete();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int SystemComm::AppInfoSession::requestNext()
|
|
{
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
buf.writeU8(NANOHUB_QUERY_APPS);
|
|
buf.writeU32(mAppInfo.size());
|
|
return sendToSystem(buf.getData(), buf.getPos());
|
|
}
|
|
|
|
int SystemComm::MemInfoSession::setup(const hub_message_t *)
|
|
{
|
|
std::lock_guard<std::mutex> _l(mLock);
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
buf.writeU8(NANOHUB_QUERY_MEMINFO);
|
|
|
|
setState(SESSION_USER);
|
|
return sendToSystem(buf.getData(), buf.getPos());
|
|
}
|
|
|
|
int SystemComm::MemInfoSession::handleRx(MessageBuf &buf)
|
|
{
|
|
std::lock_guard<std::mutex> _l(mLock);
|
|
NanohubRsp rsp(buf, true);
|
|
|
|
if (rsp.cmd != NANOHUB_QUERY_MEMINFO)
|
|
return 1;
|
|
|
|
size_t len = buf.getRoom();
|
|
|
|
if (len != sizeof(NanohubMemInfo)) {
|
|
ALOGE("%s: Invalid data size: %zu", __func__, len);
|
|
return -EINVAL;
|
|
}
|
|
if (getState() != SESSION_USER) {
|
|
ALOGE("%s: Invalid state; have %d, need %d", __func__, getState(), SESSION_USER);
|
|
return -EINVAL;
|
|
}
|
|
|
|
NanohubMemInfo mi;
|
|
readNanohubMemInfo(buf, mi);
|
|
std::vector<mem_range_t> ranges;
|
|
ranges.reserve(4);
|
|
|
|
//if each is valid, copy to output area
|
|
if (mi.sharedSz != NANOHUB_MEM_SZ_UNKNOWN &&
|
|
mi.sharedUse != NANOHUB_MEM_SZ_UNKNOWN)
|
|
ranges.push_back({
|
|
.type = HUB_MEM_TYPE_MAIN,
|
|
.total_bytes = mi.sharedSz,
|
|
.free_bytes = mi.sharedSz - mi.sharedUse,
|
|
});
|
|
|
|
if (mi.osSz != NANOHUB_MEM_SZ_UNKNOWN &&
|
|
mi.osUse != NANOHUB_MEM_SZ_UNKNOWN)
|
|
ranges.push_back({
|
|
.type = HUB_MEM_TYPE_OS,
|
|
.total_bytes = mi.osSz,
|
|
.free_bytes = mi.osSz - mi.osUse,
|
|
});
|
|
|
|
if (mi.eeSz != NANOHUB_MEM_SZ_UNKNOWN &&
|
|
mi.eeUse != NANOHUB_MEM_SZ_UNKNOWN)
|
|
ranges.push_back({
|
|
.type = HUB_MEM_TYPE_EEDATA,
|
|
.total_bytes = mi.eeSz,
|
|
.free_bytes = mi.eeSz - mi.eeUse,
|
|
});
|
|
|
|
if (mi.ramSz != NANOHUB_MEM_SZ_UNKNOWN &&
|
|
mi.ramUse != NANOHUB_MEM_SZ_UNKNOWN)
|
|
ranges.push_back({
|
|
.type = HUB_MEM_TYPE_RAM,
|
|
.total_bytes = mi.ramSz,
|
|
.free_bytes = mi.ramSz - mi.ramUse,
|
|
});
|
|
|
|
//send it out
|
|
sendToApp(CONTEXT_HUB_QUERY_MEMORY,
|
|
static_cast<const void *>(ranges.data()),
|
|
ranges.size() * sizeof(ranges[0]));
|
|
|
|
complete();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::setup(const hub_message_t *appMsg)
|
|
{
|
|
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;
|
|
|
|
switch (mCmd) {
|
|
case CONTEXT_HUB_APPS_ENABLE:
|
|
return setupMgmt(appMsg, NANOHUB_EXT_APPS_ON);
|
|
case CONTEXT_HUB_APPS_DISABLE:
|
|
return setupMgmt(appMsg, NANOHUB_EXT_APPS_OFF);
|
|
case CONTEXT_HUB_UNLOAD_APP:
|
|
return setupMgmt(appMsg, NANOHUB_EXT_APP_DELETE);
|
|
case CONTEXT_HUB_LOAD_APP:
|
|
{
|
|
mData.clear();
|
|
mData = std::vector<uint8_t>(msgData, msgData + mLen);
|
|
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;
|
|
setState(TRANSFER);
|
|
|
|
buf.writeU8(NANOHUB_START_UPLOAD);
|
|
buf.writeU8(0);
|
|
buf.writeU32(mLen);
|
|
return sendToSystem(buf.getData(), buf.getPos());
|
|
}
|
|
|
|
case CONTEXT_HUB_OS_REBOOT:
|
|
setState(REBOOT);
|
|
buf.writeU8(NANOHUB_REBOOT);
|
|
return sendToSystem(buf.getData(), buf.getPos());
|
|
}
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::setupMgmt(const hub_message_t *appMsg, uint32_t cmd)
|
|
{
|
|
const hub_app_name_t &appName = *static_cast<const hub_app_name_t*>(appMsg->message);
|
|
if (appMsg->message_len != sizeof(appName)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
buf.writeU8(cmd);
|
|
writeAppName(buf, appName);
|
|
setState(MGMT);
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos());
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleRx(MessageBuf &buf)
|
|
{
|
|
int ret = 0;
|
|
std::lock_guard<std::mutex> _l(mLock);
|
|
NanohubRsp rsp(buf);
|
|
|
|
switch (getState()) {
|
|
case TRANSFER:
|
|
ret = handleTransfer(rsp);
|
|
break;
|
|
case FINISH:
|
|
ret = handleFinish(rsp);
|
|
break;
|
|
case RUN:
|
|
ret = handleRun(rsp);
|
|
break;
|
|
case RUN_FAILED:
|
|
ret = handleRunFailed(rsp);
|
|
break;
|
|
case REBOOT:
|
|
ret = handleReboot(rsp);
|
|
break;
|
|
case MGMT:
|
|
ret = handleMgmt(rsp);
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleTransfer(NanohubRsp &rsp)
|
|
{
|
|
if (rsp.cmd != NANOHUB_CONT_UPLOAD && rsp.cmd != NANOHUB_START_UPLOAD)
|
|
return 1;
|
|
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
|
|
static_assert(NANOHUB_UPLOAD_CHUNK_SZ_MAX <= (MAX_RX_PACKET-5),
|
|
"Invalid chunk size");
|
|
|
|
if (mPos < mLen) {
|
|
uint32_t chunkSize = mLen - mPos;
|
|
|
|
if (chunkSize > NANOHUB_UPLOAD_CHUNK_SZ_MAX) {
|
|
chunkSize = NANOHUB_UPLOAD_CHUNK_SZ_MAX;
|
|
}
|
|
|
|
buf.writeU8(NANOHUB_CONT_UPLOAD);
|
|
buf.writeU32(mPos);
|
|
buf.writeRaw(&mData[mPos], chunkSize);
|
|
mPos += chunkSize;
|
|
} else {
|
|
buf.writeU8(NANOHUB_FINISH_UPLOAD);
|
|
setState(FINISH);
|
|
}
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos());
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleFinish(NanohubRsp &rsp)
|
|
{
|
|
if (rsp.cmd != NANOHUB_FINISH_UPLOAD)
|
|
return 1;
|
|
|
|
int ret = 0;
|
|
const bool success = rsp.status != 0;
|
|
mData.clear();
|
|
|
|
if (success) {
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
buf.writeU8(NANOHUB_EXT_APPS_ON);
|
|
writeAppName(buf, mAppName);
|
|
setState(RUN);
|
|
ret = sendToSystem(buf.getData(), buf.getPos());
|
|
} else {
|
|
int32_t result = NANOHUB_APP_NOT_LOADED;
|
|
|
|
sendToApp(mCmd, &result, sizeof(result));
|
|
complete();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleRun(NanohubRsp &rsp)
|
|
{
|
|
if (rsp.cmd != NANOHUB_EXT_APPS_ON)
|
|
return 1;
|
|
|
|
MgmtStatus sts = { .value = (uint32_t)rsp.status };
|
|
|
|
// op counter returns number of nanoapps that were started as result of the command
|
|
// for successful start command it must be > 0
|
|
int32_t result = sts.value > 0 && sts.op > 0 && sts.op <= 0x7F ? 0 : -1;
|
|
|
|
ALOGI("Nanohub NEW APP START: %08" PRIX32 "\n", rsp.status);
|
|
if (result != 0) {
|
|
// if nanoapp failed to start we have to unload it
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
buf.writeU8(NANOHUB_EXT_APP_DELETE);
|
|
writeAppName(buf, mAppName);
|
|
if (sendToSystem(buf.getData(), buf.getPos()) == 0) {
|
|
setState(RUN_FAILED);
|
|
return 0;
|
|
}
|
|
ALOGE("%s: failed to send DELETE for failed app\n", __func__);
|
|
}
|
|
|
|
// it is either success, and we report it, or
|
|
// it is a failure to load, and also failure to send erase command
|
|
sendToApp(mCmd, &result, sizeof(result));
|
|
complete();
|
|
return 0;
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleRunFailed(NanohubRsp &rsp)
|
|
{
|
|
if (rsp.cmd != NANOHUB_EXT_APP_DELETE)
|
|
return 1;
|
|
|
|
int32_t result = -1;
|
|
|
|
ALOGI("%s: APP DELETE [because it failed]: %08" PRIX32 "\n", __func__, rsp.status);
|
|
|
|
sendToApp(mCmd, &result, sizeof(result));
|
|
complete();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* reboot notification, when triggered by App request */
|
|
int SystemComm::AppMgmtSession::handleReboot(NanohubRsp &rsp)
|
|
{
|
|
if (rsp.cmd != NANOHUB_REBOOT)
|
|
return 1;
|
|
ALOGI("Nanohub reboot status [USER REQ]: %08" PRIX32 "\n", rsp.status);
|
|
|
|
// reboot notification is sent by SessionManager
|
|
complete();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int SystemComm::AppMgmtSession::handleMgmt(NanohubRsp &rsp)
|
|
{
|
|
bool valid = false;
|
|
|
|
int32_t result = rsp.status;
|
|
|
|
// TODO: remove this when context hub service can handle non-zero success status
|
|
if (result > 0) {
|
|
// something happened; assume it worked
|
|
result = 0;
|
|
} else if (result == 0) {
|
|
// nothing happened; this is provably an error
|
|
result = -1;
|
|
}
|
|
|
|
switch (rsp.cmd) {
|
|
case NANOHUB_EXT_APPS_OFF:
|
|
valid = mCmd == CONTEXT_HUB_APPS_DISABLE;
|
|
break;
|
|
case NANOHUB_EXT_APPS_ON:
|
|
valid = mCmd == CONTEXT_HUB_APPS_ENABLE;
|
|
break;
|
|
case NANOHUB_EXT_APP_DELETE:
|
|
valid = mCmd == CONTEXT_HUB_UNLOAD_APP;
|
|
break;
|
|
default:
|
|
return 1;
|
|
}
|
|
|
|
ALOGI("Nanohub MGMT response: CMD=%02X; STATUS=%08" PRIX32, rsp.cmd, rsp.status);
|
|
if (!valid) {
|
|
ALOGE("Invalid response for this state: APP CMD=%02X", mCmd);
|
|
return -EINVAL;
|
|
}
|
|
|
|
sendToApp(mCmd, &result, sizeof(result));
|
|
complete();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int SystemComm::KeyInfoSession::setup(const hub_message_t *) {
|
|
std::lock_guard<std::mutex> _l(mLock);
|
|
mRsaKeyData.clear();
|
|
setState(SESSION_USER);
|
|
mStatus = -EBUSY;
|
|
return requestRsaKeys();
|
|
}
|
|
|
|
int SystemComm::KeyInfoSession::handleRx(MessageBuf &buf)
|
|
{
|
|
std::lock_guard<std::mutex> _l(mLock);
|
|
NanohubRsp rsp(buf, true);
|
|
|
|
if (getState() != SESSION_USER) {
|
|
// invalid state
|
|
mStatus = -EFAULT;
|
|
return mStatus;
|
|
}
|
|
|
|
if (buf.getRoom()) {
|
|
mRsaKeyData.insert(mRsaKeyData.end(),
|
|
buf.getData() + buf.getPos(),
|
|
buf.getData() + buf.getSize());
|
|
return requestRsaKeys();
|
|
} else {
|
|
mStatus = 0;
|
|
complete();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int SystemComm::KeyInfoSession::requestRsaKeys(void)
|
|
{
|
|
char data[MAX_RX_PACKET];
|
|
MessageBuf buf(data, sizeof(data));
|
|
|
|
buf.writeU8(NANOHUB_QUERY_APPS);
|
|
buf.writeU32(mRsaKeyData.size());
|
|
|
|
return sendToSystem(buf.getData(), buf.getPos());
|
|
}
|
|
|
|
int SystemComm::doHandleRx(const nano_message *msg)
|
|
{
|
|
//we only care for messages from HostIF
|
|
if (msg->hdr.appId != mHostIfAppName.id)
|
|
return 1;
|
|
|
|
//they must all be at least 1 byte long
|
|
if (!msg->hdr.len) {
|
|
return -EINVAL;
|
|
}
|
|
MessageBuf buf(reinterpret_cast<const char*>(msg->data), msg->hdr.len);
|
|
if (NanoHub::messageTracingEnabled()) {
|
|
dumpBuffer("SYS -> HAL", mHostIfAppName, 0, buf.getData(), buf.getSize());
|
|
}
|
|
int status = mSessions.handleRx(buf);
|
|
if (status) {
|
|
// provide default handler for any system message, that is not properly handled
|
|
dumpBuffer(status > 0 ? "HAL (not handled)" : "HAL (error)",
|
|
mHostIfAppName, 0, buf.getData(), buf.getSize(), status);
|
|
status = status > 0 ? 0 : status;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
int SystemComm::SessionManager::handleRx(MessageBuf &buf)
|
|
{
|
|
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);
|
|
if (status < 0) {
|
|
session->complete();
|
|
}
|
|
}
|
|
|
|
NanohubRsp rsp(buf);
|
|
if (rsp.cmd == NANOHUB_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.status);
|
|
status = 0;
|
|
}
|
|
// report to java apps
|
|
sendToApp(CONTEXT_HUB_OS_REBOOT, &rsp.status, sizeof(rsp.status));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
int SystemComm::SessionManager::setup_and_add(int id, Session *session, const hub_message_t *appMsg)
|
|
{
|
|
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);
|
|
if (ret < 0) {
|
|
session->complete();
|
|
}
|
|
return ret;
|
|
}
|
|
return -EBUSY;
|
|
}
|
|
|
|
int SystemComm::doHandleTx(const hub_message_t *appMsg)
|
|
{
|
|
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);
|
|
if (status < 0) {
|
|
break;
|
|
}
|
|
mKeySession.wait();
|
|
status = mKeySession.getStatus();
|
|
if (status < 0) {
|
|
break;
|
|
}
|
|
}
|
|
status = mSessions.setup_and_add(CONTEXT_HUB_LOAD_APP, &mAppMgmtSession, appMsg);
|
|
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);
|
|
break;
|
|
|
|
case CONTEXT_HUB_QUERY_APPS:
|
|
status = mSessions.setup_and_add(CONTEXT_HUB_QUERY_APPS, &mAppInfoSession, appMsg);
|
|
break;
|
|
|
|
case CONTEXT_HUB_QUERY_MEMORY:
|
|
status = mSessions.setup_and_add(CONTEXT_HUB_QUERY_MEMORY, &mMemInfoSession, appMsg);
|
|
break;
|
|
|
|
default:
|
|
ALOGW("Unknown os message type %u\n", appMsg->message_type);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
}; // namespace nanohub
|
|
|
|
}; // namespace android
|