/*
 * Copyright (C) 2017 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.
 */

// LOG_TAG defined via build flag.
#ifndef LOG_TAG
#define LOG_TAG "HidlSensorManager"
#endif
#include <android-base/logging.h>

#include "SensorManager.h"

#include <sched.h>


#include "EventQueue.h"
#include "DirectReportChannel.h"
#include "utils.h"

namespace android {
namespace frameworks {
namespace sensorservice {
namespace V1_0 {
namespace implementation {

using ::android::hardware::sensors::V1_0::SensorInfo;
using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset;
using ::android::hardware::hidl_vec;
using ::android::hardware::Void;

static const char* POLL_THREAD_NAME = "hidl_ssvc_poll";

SensorManager::SensorManager(JavaVM* vm)
        : mLooper(new Looper(false /*allowNonCallbacks*/)), mStopThread(true), mJavaVm(vm) {
}

SensorManager::~SensorManager() {
    // Stops pollAll inside the thread.
    std::lock_guard<std::mutex> lock(mThreadMutex);

    mStopThread = true;
    if (mLooper != nullptr) {
        mLooper->wake();
    }
    if (mPollThread.joinable()) {
        mPollThread.join();
    }
}

// Methods from ::android::frameworks::sensorservice::V1_0::ISensorManager follow.
Return<void> SensorManager::getSensorList(getSensorList_cb _hidl_cb) {
    ::android::Sensor const* const* list;
    ssize_t count = getInternalManager().getSensorList(&list);
    if (count < 0 || !list) {
        LOG(ERROR) << "::android::SensorManager::getSensorList encounters " << count;
        _hidl_cb({}, Result::UNKNOWN_ERROR);
        return Void();
    }
    hidl_vec<SensorInfo> ret;
    ret.resize(static_cast<size_t>(count));
    for (ssize_t i = 0; i < count; ++i) {
        ret[i] = convertSensor(*list[i]);
    }
    _hidl_cb(ret, Result::OK);
    return Void();
}

Return<void> SensorManager::getDefaultSensor(SensorType type, getDefaultSensor_cb _hidl_cb) {
    ::android::Sensor const* sensor = getInternalManager().getDefaultSensor(static_cast<int>(type));
    if (!sensor) {
        _hidl_cb({}, Result::NOT_EXIST);
        return Void();
    }
    _hidl_cb(convertSensor(*sensor), Result::OK);
    return Void();
}

template<typename Callback>
void createDirectChannel(::android::SensorManager& manager, size_t size, int type,
        const native_handle_t* handle, const Callback& _hidl_cb) {

    int channelId = manager.createDirectChannel(
        size, type, handle);
    if (channelId < 0) {
        _hidl_cb(nullptr, convertResult(channelId));
        return;
    }
    if (channelId == 0) {
        _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
        return;
    }

    _hidl_cb(sp<IDirectReportChannel>(new DirectReportChannel(manager, channelId)),
            Result::OK);
}

Return<void> SensorManager::createAshmemDirectChannel(
        const hidl_memory& mem, uint64_t size,
        createAshmemDirectChannel_cb _hidl_cb) {
    if (size > mem.size() || size < (uint64_t)SensorsEventFormatOffset::TOTAL_LENGTH) {
        _hidl_cb(nullptr, Result::BAD_VALUE);
        return Void();
    }

    createDirectChannel(getInternalManager(), size, SENSOR_DIRECT_MEM_TYPE_ASHMEM,
            mem.handle(), _hidl_cb);

    return Void();
}

Return<void> SensorManager::createGrallocDirectChannel(
        const hidl_handle& buffer, uint64_t size,
        createGrallocDirectChannel_cb _hidl_cb) {

    createDirectChannel(getInternalManager(), size, SENSOR_DIRECT_MEM_TYPE_GRALLOC,
            buffer.getNativeHandle(), _hidl_cb);

    return Void();
}

/* One global looper for all event queues created from this SensorManager. */
sp<Looper> SensorManager::getLooper() {
    std::lock_guard<std::mutex> lock(mThreadMutex);

    if (!mPollThread.joinable()) {
        // if thread not initialized, start thread
        mStopThread = false;
        std::thread pollThread{[&stopThread = mStopThread, looper = mLooper, javaVm = mJavaVm] {

            struct sched_param p = {0};
            p.sched_priority = 10;
            if (sched_setscheduler(0 /* current thread*/, SCHED_FIFO, &p) != 0) {
                LOG(WARNING) << "Could not use SCHED_FIFO for looper thread: "
                        << strerror(errno);
            }

            // set looper
            Looper::setForThread(looper);

            // Attach the thread to JavaVM so that pollAll do not crash if the thread
            // eventually calls into Java.
            JavaVMAttachArgs args{
                .version = JNI_VERSION_1_2,
                .name = POLL_THREAD_NAME,
                .group = NULL
            };
            JNIEnv* env;
            if (javaVm->AttachCurrentThread(&env, &args) != JNI_OK) {
                LOG(FATAL) << "Cannot attach SensorManager looper thread to Java VM.";
            }

            LOG(INFO) << POLL_THREAD_NAME << " started.";
            for (;;) {
                int pollResult = looper->pollAll(-1 /* timeout */);
                if (pollResult == Looper::POLL_WAKE) {
                    if (stopThread == true) {
                        LOG(INFO) << POLL_THREAD_NAME << ": requested to stop";
                        break;
                    } else {
                        LOG(INFO) << POLL_THREAD_NAME << ": spurious wake up, back to work";
                    }
                } else {
                    LOG(ERROR) << POLL_THREAD_NAME << ": Looper::pollAll returns unexpected "
                               << pollResult;
                    break;
                }
            }

            if (javaVm->DetachCurrentThread() != JNI_OK) {
                LOG(ERROR) << "Cannot detach SensorManager looper thread from Java VM.";
            }

            LOG(INFO) << POLL_THREAD_NAME << " is terminated.";
        }};
        mPollThread = std::move(pollThread);
    }
    return mLooper;
}

::android::SensorManager& SensorManager::getInternalManager() {
    std::lock_guard<std::mutex> lock(mInternalManagerMutex);
    if (mInternalManager == nullptr) {
        mInternalManager = &::android::SensorManager::getInstanceForPackage(
                String16(ISensorManager::descriptor));
    }
    return *mInternalManager;
}

Return<void> SensorManager::createEventQueue(
        const sp<IEventQueueCallback> &callback, createEventQueue_cb _hidl_cb) {
    if (callback == nullptr) {
        _hidl_cb(nullptr, Result::BAD_VALUE);
        return Void();
    }

    sp<::android::Looper> looper = getLooper();
    if (looper == nullptr) {
        LOG(ERROR) << "::android::SensorManager::createEventQueue cannot initialize looper";
        _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
        return Void();
    }

    sp<::android::SensorEventQueue> internalQueue = getInternalManager().createEventQueue();
    if (internalQueue == nullptr) {
        LOG(WARNING) << "::android::SensorManager::createEventQueue returns nullptr.";
        _hidl_cb(nullptr, Result::UNKNOWN_ERROR);
        return Void();
    }

    sp<IEventQueue> queue = new EventQueue(callback, looper, internalQueue);
    _hidl_cb(queue, Result::OK);

    return Void();
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace sensorservice
}  // namespace frameworks
}  // namespace android
