/*
 * 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.
 */

#include "Contexthub.h"

#include <inttypes.h>

#include <log/log.h>

#include <android/hardware/contexthub/1.0/IContexthub.h>
#include <hardware/context_hub.h>
#include <sys/endian.h>

#undef LOG_TAG
#define LOG_TAG "ContextHubHalAdapter"

namespace android {
namespace hardware {
namespace contexthub {
namespace V1_0 {
namespace implementation {

static constexpr uint64_t ALL_APPS = UINT64_C(0xFFFFFFFFFFFFFFFF);

Contexthub::Contexthub()
        : mInitCheck(NO_INIT),
          mContextHubModule(nullptr),
          mIsTransactionPending(false) {
    const hw_module_t *module;

    mInitCheck = hw_get_module(CONTEXT_HUB_MODULE_ID, &module);

    if (mInitCheck != OK) {
        ALOGE("Could not load %s module: %s", CONTEXT_HUB_MODULE_ID, strerror(-mInitCheck));
    } else if (module == nullptr) {
        ALOGE("hal returned succes but a null module!");
        // Assign an error, this should not really happen...
        mInitCheck = UNKNOWN_ERROR;
    } else {
        ALOGI("Loaded Context Hub module");
        mContextHubModule = reinterpret_cast<const context_hub_module_t *>(module);
    }
}

bool Contexthub::setOsAppAsDestination(hub_message_t *msg, int hubId) {
    if (!isValidHubId(hubId)) {
        ALOGW("%s: Hub information is null for hubHandle %d",
              __FUNCTION__,
              hubId);
        return false;
    } else {
        msg->app_name = mCachedHubInfo[hubId].osAppName;
        return true;
    }
}

Return<void> Contexthub::getHubs(getHubs_cb _hidl_cb) {
    std::vector<ContextHub> hubs;
    if (isInitialized()) {
        const context_hub_t *hubArray = nullptr;
        size_t numHubs;

        // Explicitly discarding const. HAL method discards it.
        numHubs = mContextHubModule->get_hubs(const_cast<context_hub_module_t *>(mContextHubModule),
                                              &hubArray);
        ALOGI("Context Hub Hal Adapter reports %zu hubs", numHubs);

        mCachedHubInfo.clear();

        for (size_t i = 0; i < numHubs; i++) {
            CachedHubInformation info;
            ContextHub c;

            c.hubId = hubArray[i].hub_id;
            c.name = hubArray[i].name;
            c.vendor = hubArray[i].vendor;
            c.toolchain = hubArray[i].toolchain;
            c.toolchainVersion = hubArray[i].toolchain_version;
            c.platformVersion = hubArray[i].platform_version;
            c.maxSupportedMsgLen = hubArray[i].max_supported_msg_len;
            c.peakMips = hubArray[i].peak_mips;
            c.peakPowerDrawMw = hubArray[i].peak_power_draw_mw;
            c.stoppedPowerDrawMw = hubArray[i].stopped_power_draw_mw;
            c.sleepPowerDrawMw = hubArray[i].sleep_power_draw_mw;

            info.callBack = nullptr;
            info.osAppName = hubArray[i].os_app_name;
            mCachedHubInfo[hubArray[i].hub_id] = info;

            hubs.push_back(c);
        }
    } else {
        ALOGW("Context Hub Hal Adapter not initialized");
    }

    _hidl_cb(hubs);
    return Void();
}

bool Contexthub::isValidHubId(uint32_t hubId) {
    if (!mCachedHubInfo.count(hubId)) {
        ALOGW("Hub information not found for hubId %" PRIu32, hubId);
        return false;
    } else {
        return true;
    }
}

sp<IContexthubCallback> Contexthub::getCallBackForHubId(uint32_t hubId) {
    if (!isValidHubId(hubId)) {
        return nullptr;
    } else {
        return mCachedHubInfo[hubId].callBack;
    }
}

Return<Result> Contexthub::sendMessageToHub(uint32_t hubId,
                                            const ContextHubMsg &msg) {
    if (!isInitialized()) {
        return Result::NOT_INIT;
    }

    if (!isValidHubId(hubId) || msg.msg.size() > UINT32_MAX) {
        return Result::BAD_PARAMS;
    }

    hub_message_t txMsg = {
        .app_name.id = msg.appName,
        .message_type = msg.msgType,
        .message_len = static_cast<uint32_t>(msg.msg.size()), // Note the check above
        .message = static_cast<const uint8_t *>(msg.msg.data()),
    };

    ALOGI("Sending msg of type %" PRIu32 ", size %" PRIu32 " to app 0x%" PRIx64,
          txMsg.message_type,
          txMsg.message_len,
          txMsg.app_name.id);

    if(mContextHubModule->send_message(hubId, &txMsg) != 0) {
        return Result::TRANSACTION_FAILED;
    }

    return Result::OK;
}

Return<Result> Contexthub::reboot(uint32_t hubId) {
    if (!isInitialized()) {
      return Result::NOT_INIT;
    }

    hub_message_t msg;

    if (setOsAppAsDestination(&msg, hubId) == false) {
        return Result::BAD_PARAMS;
    }

    msg.message_type = CONTEXT_HUB_OS_REBOOT;
    msg.message_len = 0;
    msg.message = nullptr;

    if(mContextHubModule->send_message(hubId, &msg) != 0) {
        return Result::TRANSACTION_FAILED;
    } else {
        return Result::OK;
    }
}

Return<Result> Contexthub::registerCallback(uint32_t hubId,
                                            const sp<IContexthubCallback> &cb) {
    Return<Result> retVal = Result::BAD_PARAMS;

    if (!isInitialized()) {
        // Not initilalized
        ALOGW("Context hub not initialized successfully");
        retVal = Result::NOT_INIT;
    } else if (!isValidHubId(hubId)) {
        // Initialized, but hubId is  not valid
        retVal = Result::BAD_PARAMS;
    } else if (mContextHubModule->subscribe_messages(hubId,
                                                     contextHubCb,
                                                     this) == 0) {
        // Initialized && valid hub && subscription successful
        retVal = Result::OK;
        mCachedHubInfo[hubId].callBack = cb;
    } else {
        // Initalized && valid hubId - but subscription unsuccessful
        // This is likely an internal error in the HAL implementation, but we
        // cannot add more information.
        ALOGW("Could not subscribe to the hub for callback");
        retVal = Result::UNKNOWN_FAILURE;
    }

    return retVal;
}

static bool isValidOsStatus(const uint8_t *msg,
                            size_t msgLen,
                            status_response_t *rsp) {
    // Workaround a bug in some HALs
    if (msgLen == 1) {
        rsp->result = msg[0];
        return true;
    }

    if (msg == nullptr || msgLen != sizeof(*rsp)) {
        ALOGI("Received invalid response (is null : %d, size %zu)",
              msg == nullptr ? 1 : 0,
              msgLen);
        return false;
    }

    memcpy(rsp, msg, sizeof(*rsp));

    // No sanity checks on return values
    return true;
}

int Contexthub::handleOsMessage(sp<IContexthubCallback> cb,
                                uint32_t msgType,
                                const uint8_t *msg,
                                int msgLen) {
    int retVal = -1;


    switch(msgType) {
        case CONTEXT_HUB_APPS_ENABLE:
        case CONTEXT_HUB_APPS_DISABLE:
        case CONTEXT_HUB_LOAD_APP:
        case CONTEXT_HUB_UNLOAD_APP:
        {
            struct status_response_t rsp;
            TransactionResult result;
            if (isValidOsStatus(msg, msgLen, &rsp) && rsp.result == 0) {
                retVal = 0;
                result = TransactionResult::SUCCESS;
            } else {
                result = TransactionResult::FAILURE;
            }

            if (cb != nullptr) {
                cb->handleTxnResult(mTransactionId, result);
            }
            retVal = 0;
            mIsTransactionPending = false;
            break;
        }

        case CONTEXT_HUB_QUERY_APPS:
        {
            std::vector<HubAppInfo> apps;
            int numApps = msgLen / sizeof(hub_app_info);
            const hub_app_info *unalignedInfoAddr = reinterpret_cast<const hub_app_info *>(msg);

            for (int i = 0; i < numApps; i++) {
                hub_app_info query_info;
                memcpy(&query_info, &unalignedInfoAddr[i], sizeof(query_info));
                HubAppInfo app;
                app.appId = query_info.app_name.id;
                app.version = query_info.version;
                // TODO :: Add memory ranges

                apps.push_back(app);
            }

            if (cb != nullptr) {
                cb->handleAppsInfo(apps);
            }
            retVal = 0;
            break;
        }

        case CONTEXT_HUB_QUERY_MEMORY:
        {
            // Deferring this use
            retVal = 0;
            break;
        }

        case CONTEXT_HUB_OS_REBOOT:
        {
            mIsTransactionPending = false;
            if (cb != nullptr) {
                cb->handleHubEvent(AsyncEventType::RESTARTED);
            }
            retVal = 0;
            break;
        }

        default:
        {
            retVal = -1;
            break;
        }
      }

      return retVal;
}

int Contexthub::contextHubCb(uint32_t hubId,
                             const struct hub_message_t *rxMsg,
                             void *cookie) {
    Contexthub *obj = static_cast<Contexthub *>(cookie);

    if (rxMsg == nullptr) {
        ALOGW("Ignoring NULL message");
        return -1;
    }

    if (!obj->isValidHubId(hubId)) {
        ALOGW("Invalid hub Id %" PRIu32, hubId);
        return -1;
    }

    sp<IContexthubCallback> cb = obj->getCallBackForHubId(hubId);

    if (cb == nullptr) {
        // This should not ever happen
        ALOGW("No callback registered, returning");
        return -1;
    }

    if (rxMsg->message_type < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE) {
        obj->handleOsMessage(cb,
                             rxMsg->message_type,
                             static_cast<const uint8_t *>(rxMsg->message),
                             rxMsg->message_len);
    } else {
        ContextHubMsg msg;

        msg.appName = rxMsg->app_name.id;
        msg.msgType = rxMsg->message_type;
        msg.msg = std::vector<uint8_t>(static_cast<const uint8_t *>(rxMsg->message),
                                       static_cast<const uint8_t *>(rxMsg->message) +
                                       rxMsg->message_len);

        cb->handleClientMsg(msg);
    }

    return 0;
}

Return<Result> Contexthub::unloadNanoApp(uint32_t hubId,
                                         uint64_t appId,
                                         uint32_t transactionId) {
    if (!isInitialized()) {
      return Result::NOT_INIT;
    }

    if (mIsTransactionPending) {
        return Result::TRANSACTION_PENDING;
    }

    hub_message_t msg;

    if (setOsAppAsDestination(&msg, hubId) == false) {
        return Result::BAD_PARAMS;
    }

    struct apps_disable_request_t req;

    msg.message_type = CONTEXT_HUB_UNLOAD_APP;
    msg.message_len = sizeof(req);
    msg.message = &req;
    req.app_name.id = appId;

    if(mContextHubModule->send_message(hubId, &msg) != 0) {
        return Result::TRANSACTION_FAILED;
    } else {
        mTransactionId = transactionId;
        mIsTransactionPending = true;
        return Result::OK;
    }
}

Return<Result> Contexthub::loadNanoApp(uint32_t hubId,
                                       const NanoAppBinary& appBinary,
                                       uint32_t transactionId) {
    if (!isInitialized()) {
      return Result::NOT_INIT;
    }

    if (mIsTransactionPending) {
        return Result::TRANSACTION_PENDING;
    }

    hub_message_t hubMsg;

    if (setOsAppAsDestination(&hubMsg, hubId) == false) {
        return Result::BAD_PARAMS;
    }

    // Data from the nanoapp header is passed through HIDL as explicit fields,
    // but the legacy HAL expects it prepended to the binary, therefore we must
    // reconstruct it here prior to passing to the legacy HAL.
    uint32_t targetChreApiVersion =
        (appBinary.targetChreApiMajorVersion << 24) |
        (appBinary.targetChreApiMinorVersion << 16);
    const struct nano_app_binary_t header = {
        .header_version = htole32(1),
        .magic          = htole32(NANOAPP_MAGIC),
        .app_id.id      = htole64(appBinary.appId),
        .app_version    = htole32(appBinary.appVersion),
        .flags          = htole32(appBinary.flags),
        .hw_hub_type    = htole64(0),
        .reserved[0]    = htole32(targetChreApiVersion),
        .reserved[1]    = 0,
    };
    const uint8_t *headerBytes = reinterpret_cast<const uint8_t *>(&header);

    std::vector<uint8_t> binaryWithHeader(appBinary.customBinary);
    binaryWithHeader.insert(binaryWithHeader.begin(),
                            headerBytes,
                            headerBytes + sizeof(header));

    hubMsg.message_type = CONTEXT_HUB_LOAD_APP;
    hubMsg.message_len = binaryWithHeader.size();
    hubMsg.message = binaryWithHeader.data();

    if (mContextHubModule->send_message(hubId, &hubMsg) != 0) {
        return Result::TRANSACTION_FAILED;
    } else {
        mTransactionId = transactionId;
        mIsTransactionPending = true;
        return Result::OK;
    }
}

Return<Result> Contexthub::enableNanoApp(uint32_t hubId,
                                         uint64_t appId,
                                         uint32_t transactionId) {
    if (!isInitialized()) {
      return Result::NOT_INIT;
    }

    if (mIsTransactionPending) {
        return Result::TRANSACTION_PENDING;
    }

    hub_message_t msg;

    if (setOsAppAsDestination(&msg, hubId) == false) {
        return Result::BAD_PARAMS;
    }

    struct apps_enable_request_t req;

    msg.message_type = CONTEXT_HUB_APPS_ENABLE;
    msg.message_len = sizeof(req);
    req.app_name.id = appId;
    msg.message = &req;

    if(mContextHubModule->send_message(hubId, &msg) != 0) {
        return Result::TRANSACTION_FAILED;
    } else {
        mTransactionId = transactionId;
        mIsTransactionPending = true;
        return Result::OK;
    }
}

Return<Result> Contexthub::disableNanoApp(uint32_t hubId,
                                          uint64_t appId,
                                          uint32_t transactionId) {
    if (!isInitialized()) {
      return Result::NOT_INIT;
    }

    if (mIsTransactionPending) {
        return Result::TRANSACTION_PENDING;
    }

    hub_message_t msg;

    if (setOsAppAsDestination(&msg, hubId) == false) {
        return Result::BAD_PARAMS;
    }

    struct apps_disable_request_t req;

    msg.message_type = CONTEXT_HUB_APPS_DISABLE;
    msg.message_len = sizeof(req);
    req.app_name.id = appId;
    msg.message = &req;

    if(mContextHubModule->send_message(hubId, &msg) != 0) {
        return Result::TRANSACTION_FAILED;
    } else {
        mTransactionId = transactionId;
        mIsTransactionPending = true;
        return Result::OK;
    }
}

Return<Result> Contexthub::queryApps(uint32_t hubId) {
    if (!isInitialized()) {
      return Result::NOT_INIT;
    }

    hub_message_t msg;

    if (setOsAppAsDestination(&msg, hubId) == false) {
        ALOGW("Could not find hubId %" PRIu32, hubId);
        return Result::BAD_PARAMS;
    }

    query_apps_request_t payload;
    payload.app_name.id = ALL_APPS; // TODO : Pass this in as a parameter
    msg.message = &payload;
    msg.message_len = sizeof(payload);
    msg.message_type = CONTEXT_HUB_QUERY_APPS;

    if(mContextHubModule->send_message(hubId, &msg) != 0) {
        ALOGW("Query Apps sendMessage failed");
        return Result::TRANSACTION_FAILED;
    }

    return Result::OK;
}

bool Contexthub::isInitialized() {
    return (mInitCheck == OK && mContextHubModule != nullptr);
}

IContexthub *HIDL_FETCH_IContexthub(const char * halName) {
    ALOGI("%s Called for %s", __FUNCTION__, halName);
    Contexthub *contexthub = new Contexthub;

    if (!contexthub->isInitialized()) {
        delete contexthub;
        contexthub = nullptr;
    }

    return contexthub;
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace contexthub
}  // namespace hardware
}  // namespace android
