/*
 * 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({
                .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, 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 = 0;
    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::StyledWriter writer;
    std::string serializedSettings(writer.write(*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::Reader reader;
        bool valid = reader.parse(str, *in);
        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
