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

#include <hwbinder/IPCThreadState.h>
#include <utils/String8.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();
    }

    String8 package(String8::format("hidl_client_pid_%d",
                                    android::hardware::IPCThreadState::self()->getCallingPid()));
    sp<::android::SensorEventQueue> internalQueue = getInternalManager().createEventQueue(package);
    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
