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

#define DEBUG false  // STOPSHIP if true
#include "Log.h"

#include "StatsService.h"
#include "logd/LogReader.h"
#include "socket/StatsSocketListener.h"

#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <binder/Status.h>
#include <utils/Looper.h>
#include <utils/StrongPointer.h>

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

using namespace android;
using namespace android::os::statsd;

const bool kUseLogd = false;
const bool kUseStatsdSocket = true;

/**
 * Thread function data.
 */
struct log_reader_thread_data {
    sp<StatsService> service;
};

/**
 * Thread func for where the log reader runs.
 */
static void* log_reader_thread_func(void* cookie) {
    log_reader_thread_data* data = static_cast<log_reader_thread_data*>(cookie);
    sp<LogReader> reader = new LogReader(data->service);

    // Run the read loop. Never returns.
    reader->Run();

    ALOGW("statsd LogReader.Run() is not supposed to return.");

    delete data;
    return NULL;
}

/**
 * Creates and starts the thread to own the LogReader.
 */
static status_t start_log_reader_thread(const sp<StatsService>& service) {
    status_t err;
    pthread_attr_t attr;
    pthread_t thread;

    // Thread data.
    log_reader_thread_data* data = new log_reader_thread_data();
    data->service = service;

    // Create the thread
    err = pthread_attr_init(&attr);
    if (err != NO_ERROR) {
        return err;
    }
    // TODO: Do we need to tweak thread priority?
    err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if (err != NO_ERROR) {
        pthread_attr_destroy(&attr);
        return err;
    }
    err = pthread_create(&thread, &attr, log_reader_thread_func, static_cast<void*>(data));
    if (err != NO_ERROR) {
        pthread_attr_destroy(&attr);
        return err;
    }
    pthread_attr_destroy(&attr);

    return NO_ERROR;
}


sp<StatsService> gStatsService = nullptr;

void sigHandler(int sig) {
    if (gStatsService != nullptr) {
        gStatsService->Terminate();
    }
}

void registerSigHandler()
{
    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sa.sa_handler = sigHandler;
    sigaction(SIGHUP, &sa, nullptr);
    sigaction(SIGINT, &sa, nullptr);
    sigaction(SIGQUIT, &sa, nullptr);
    sigaction(SIGTERM, &sa, nullptr);
}

int main(int /*argc*/, char** /*argv*/) {
    // Set up the looper
    sp<Looper> looper(Looper::prepare(0 /* opts */));

    // Set up the binder
    sp<ProcessState> ps(ProcessState::self());
    ps->setThreadPoolMaxThreadCount(9);
    ps->startThreadPool();
    ps->giveThreadPoolName();
    IPCThreadState::self()->disableBackgroundScheduling(true);

    // Create the service
    gStatsService = new StatsService(looper);
    if (defaultServiceManager()->addService(String16("stats"), gStatsService) != 0) {
        ALOGE("Failed to add service");
        return -1;
    }

    registerSigHandler();

    gStatsService->sayHiToStatsCompanion();

    gStatsService->Startup();

    sp<StatsSocketListener> socketListener = new StatsSocketListener(gStatsService);

    if (kUseLogd) {
        ALOGI("using logd");
        // Start the log reader thread
        status_t err = start_log_reader_thread(gStatsService);
        if (err != NO_ERROR) {
            return 1;
        }
    }

    if (kUseStatsdSocket) {
        ALOGI("using statsd socket");
        // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value
        if (socketListener->startListener(600)) {
            exit(1);
        }
    }

    // Loop forever -- the reports run on this thread in a handler, and the
    // binder calls remain responsive in their pool of one thread.
    while (true) {
        looper->pollAll(-1 /* timeoutMillis */);
    }
    ALOGW("statsd escaped from its loop.");

    return 1;
}
