/*
 * Copyright (C) 2018 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 <pixelstats/DropDetect.h>

#include <chre/util/nanoapp/app_id.h>
#include <chre_host/host_protocol_host.h>
#include <chre_host/socket_client.h>

#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
#include <pixelstats/StatsHelper.h>

#define LOG_TAG "pixelstats-vendor"
#include <log/log.h>

#include <inttypes.h>
#include <math.h>

using aidl::android::frameworks::stats::IStats;
using aidl::android::frameworks::stats::VendorAtom;
using aidl::android::frameworks::stats::VendorAtomValue;
using android::sp;
using android::chre::HostProtocolHost;
using android::chre::IChreMessageHandlers;
using android::chre::SocketClient;
using android::hardware::google::pixel::PixelAtoms::VendorPhysicalDropDetected;

// following convention of CHRE code.
namespace fbs = ::chre::fbs;

namespace android {
namespace hardware {
namespace google {
namespace pixel {

namespace {  // anonymous namespace for file-local definitions

// The following two structs are defined in nanoapps/drop/messaging.h
// by the DropDetect nanoapp.
struct __attribute__((__packed__)) DropEventPayload {
    float confidence;
    float accel_magnitude_peak;
    int32_t free_fall_duration_ns;
};

struct __attribute__((__packed__)) DropEventPayloadV2 {
    uint64_t free_fall_duration_ns;
    float impact_accel_x;
    float impact_accel_y;
    float impact_accel_z;
};

// This enum is defined in nanoapps/drop/messaging.h
// by the DropDetect nanoapp.
enum DropConstants {
    kDropEnableRequest = 1,
    kDropEnableNotification = 2,
    kDropDisableRequest = 3,
    kDropDisableNotification = 4,
    kDropEventDetection = 5,
    kDropEventDetectionV2 = 6,
};

void requestNanoappList(SocketClient *client) {
    if (client != nullptr) {
        flatbuffers::FlatBufferBuilder builder(64);
        HostProtocolHost::encodeNanoappListRequest(builder);

        if (!client->sendMessage(builder.GetBufferPointer(), builder.GetSize())) {
            ALOGE("Failed to send NanoappList request");
        }
    }
}

}  // namespace

DropDetect::DropDetect(const uint64_t drop_detect_app_id) : kDropDetectAppId(drop_detect_app_id) {}

sp<DropDetect> DropDetect::start(const uint64_t drop_detect_app_id, const char *const chre_socket) {
    sp<DropDetect> dropDetect = new DropDetect(drop_detect_app_id);
    if (!dropDetect->connectInBackground(chre_socket, dropDetect)) {
        ALOGE("Couldn't connect to CHRE socket");
        return nullptr;
    }
    return dropDetect;
}

void DropDetect::onConnected() {
    requestNanoappList(this);
}

/**
 * Decode unix socket msgs to CHRE messages, and call the appropriate
 * callback depending on the CHRE message.
 */
void DropDetect::onMessageReceived(const void *data, size_t length) {
    if (!HostProtocolHost::decodeMessageFromChre(data, length, *this)) {
        ALOGE("Failed to decode message");
    }
}

/**
 * Handle the response of a NanoappList request.
 * Ensure that the Drop Detect nanoapp is running.
 */
void DropDetect::handleNanoappListResponse(const fbs::NanoappListResponseT &response) {
    for (const std::unique_ptr<fbs::NanoappListEntryT> &nanoapp : response.nanoapps) {
        if (nanoapp->app_id == kDropDetectAppId) {
            if (!nanoapp->enabled)
                ALOGE("Drop Detect app not enabled");
            else
                ALOGI("Drop Detect enabled");
            return;
        }
    }
    ALOGE("Drop Detect app not found");
}

static VendorPhysicalDropDetected dropEventFromNanoappPayload(const struct DropEventPayload *p) {
    ALOGI("Received drop detect message! Confidence %f Peak %f Duration %g",
          p->confidence, p->accel_magnitude_peak, p->free_fall_duration_ns / 1e9);

    uint8_t confidence = p->confidence * 100;
    confidence = std::min<int>(confidence, 100);
    confidence = std::max<int>(0, confidence);
    int32_t accel_magnitude_peak_1000ths_g = p->accel_magnitude_peak * 1000.0;
    int32_t free_fall_duration_ms = p->free_fall_duration_ns / 1000000;

    VendorPhysicalDropDetected drop_info;
    drop_info.set_confidence_pctg(confidence);
    drop_info.set_accel_peak_thousandths_g(accel_magnitude_peak_1000ths_g);
    drop_info.set_freefall_time_millis(free_fall_duration_ms);
    return drop_info;
}

static VendorPhysicalDropDetected dropEventFromNanoappPayload(const struct DropEventPayloadV2 *p) {
    ALOGI("Received drop detect message: "
          "duration %g ms, impact acceleration: x = %f, y = %f, z = %f",
          p->free_fall_duration_ns / 1e6,
          p->impact_accel_x,
          p->impact_accel_y,
          p->impact_accel_z);

    float impact_magnitude = sqrt(p->impact_accel_x * p->impact_accel_x +
                                  p->impact_accel_y * p->impact_accel_y +
                                  p->impact_accel_z * p->impact_accel_z);
    /* Scale impact magnitude as percentage between [50, 100] m/s2. */
    constexpr float min_confidence_magnitude = 50;
    constexpr float max_confidence_magnitude = 100;
    uint8_t confidence_percentage =
        impact_magnitude < min_confidence_magnitude ? 0 :
        impact_magnitude > max_confidence_magnitude ? 100 :
            (impact_magnitude - min_confidence_magnitude) /
            (max_confidence_magnitude - min_confidence_magnitude) * 100;

    int32_t free_fall_duration_ms = static_cast<int32_t>(p->free_fall_duration_ns / 1000000);

    VendorPhysicalDropDetected drop_info;
    drop_info.set_confidence_pctg(confidence_percentage);
    drop_info.set_accel_peak_thousandths_g(static_cast<int32_t>(impact_magnitude * 1000));
    drop_info.set_freefall_time_millis(free_fall_duration_ms);
    return drop_info;
}

static void reportDropEventToStatsd(const VendorPhysicalDropDetected &drop) {
    const std::shared_ptr<IStats> stats_client = getStatsService();
    if (!stats_client) {
        ALOGE("Unable to get AIDL Stats service");
        return;
    }

    reportPhysicalDropDetected(stats_client, drop);
}

/**
 * listen for messages from the DropDetect nanoapp and report them to
 * PixelStats.
 */
void DropDetect::handleNanoappMessage(const fbs::NanoappMessageT &message) {
    if (message.app_id != kDropDetectAppId)
        return;

    if (message.message_type == kDropEventDetection &&
        message.message.size() >= sizeof(struct DropEventPayload)) {
        reportDropEventToStatsd(dropEventFromNanoappPayload(
            reinterpret_cast<const struct DropEventPayload *>(&message.message[0])));
    } else if (message.message_type == kDropEventDetectionV2 &&
               message.message.size() >= sizeof(struct DropEventPayloadV2)) {
        reportDropEventToStatsd(dropEventFromNanoappPayload(
            reinterpret_cast<const struct DropEventPayloadV2 *>(&message.message[0])));
    }
}

}  // namespace pixel
}  // namespace google
}  // namespace hardware
}  // namespace android
