/*
 * Copyright (C) 2013 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/license/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 LOG_TAG "FlpHardwareProvider"
#define LOG_NDEBUG  0

#define WAKE_LOCK_NAME  "FLP"
#define LOCATION_CLASS_NAME "android/location/Location"

#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/Log.h"
#include "hardware/fused_location.h"
#include "hardware_legacy/power.h"

static jobject sCallbacksObj = NULL;
static JNIEnv *sCallbackEnv = NULL;
static hw_device_t* sHardwareDevice = NULL;

static jmethodID sOnLocationReport = NULL;
static jmethodID sOnDataReport = NULL;
static jmethodID sOnGeofenceTransition = NULL;
static jmethodID sOnGeofenceMonitorStatus = NULL;
static jmethodID sOnGeofenceAdd = NULL;
static jmethodID sOnGeofenceRemove = NULL;
static jmethodID sOnGeofencePause = NULL;
static jmethodID sOnGeofenceResume = NULL;

static const FlpLocationInterface* sFlpInterface = NULL;
static const FlpDiagnosticInterface* sFlpDiagnosticInterface = NULL;
static const FlpGeofencingInterface* sFlpGeofencingInterface = NULL;
static const FlpDeviceContextInterface* sFlpDeviceContextInterface = NULL;

namespace android {

static inline void CheckExceptions(JNIEnv* env, const char* methodName) {
  if(!env->ExceptionCheck()) {
    return;
  }

  ALOGE("An exception was thrown by '%s'.", methodName);
  LOGE_EX(env);
  env->ExceptionClear();
}

static inline void ThrowOnError(
    JNIEnv* env,
    int resultCode,
    const char* methodName) {
  if(resultCode == FLP_RESULT_SUCCESS) {
    return;
  }

  ALOGE("Error %d in '%s'", resultCode, methodName);
  env->FatalError(methodName);
}

static bool IsValidCallbackThread() {
  JNIEnv* env = AndroidRuntime::getJNIEnv();

  if(sCallbackEnv == NULL || sCallbackEnv != env) {
    ALOGE("CallbackThread check fail: env=%p, expected=%p", env, sCallbackEnv);
    return false;
  }

  return true;
}

static int SetThreadEvent(ThreadEvent event) {
  JavaVM* javaVm = AndroidRuntime::getJavaVM();

  switch(event) {
    case ASSOCIATE_JVM:
    {
      if(sCallbackEnv != NULL) {
        ALOGE(
            "Attempted to associate callback in '%s'. Callback already associated.",
            __FUNCTION__
            );
        return FLP_RESULT_ERROR;
      }

      JavaVMAttachArgs args = {
          JNI_VERSION_1_6,
          "FLP Service Callback Thread",
          /* group */ NULL
      };

      jint attachResult = javaVm->AttachCurrentThread(&sCallbackEnv, &args);
      if (attachResult != 0) {
        ALOGE("Callback thread attachment error: %d", attachResult);
        return FLP_RESULT_ERROR;
      }

      ALOGV("Callback thread attached: %p", sCallbackEnv);
      break;
    }
    case DISASSOCIATE_JVM:
    {
      if (!IsValidCallbackThread()) {
        ALOGE(
            "Attempted to dissasociate an unnownk callback thread : '%s'.",
            __FUNCTION__
            );
        return FLP_RESULT_ERROR;
      }

      if (javaVm->DetachCurrentThread() != 0) {
        return FLP_RESULT_ERROR;
      }

      sCallbackEnv = NULL;
      break;
    }
    default:
      ALOGE("Invalid ThreadEvent request %d", event);
      return FLP_RESULT_ERROR;
  }

  return FLP_RESULT_SUCCESS;
}

/*
 * Initializes the FlpHardwareProvider class from the native side by opening
 * the HW module and obtaining the proper interfaces.
 */
static void ClassInit(JNIEnv* env, jclass clazz) {
  // get references to the Java provider methods
  sOnLocationReport = env->GetMethodID(
      clazz,
      "onLocationReport",
      "([Landroid/location/Location;)V");
  sOnDataReport = env->GetMethodID(
      clazz,
      "onDataReport",
      "(Ljava/lang/String;)V"
      );
  sOnGeofenceTransition = env->GetMethodID(
      clazz,
      "onGeofenceTransition",
      "(ILandroid/location/Location;IJI)V"
      );
  sOnGeofenceMonitorStatus = env->GetMethodID(
      clazz,
      "onGeofenceMonitorStatus",
      "(IILandroid/location/Location;)V"
      );
  sOnGeofenceAdd = env->GetMethodID(clazz, "onGeofenceAdd", "(II)V");
  sOnGeofenceRemove = env->GetMethodID(clazz, "onGeofenceRemove", "(II)V");
  sOnGeofencePause = env->GetMethodID(clazz, "onGeofencePause", "(II)V");
  sOnGeofenceResume = env->GetMethodID(clazz, "onGeofenceResume", "(II)V");
}

/*
 * Helper function to unwrap a java object back into a FlpLocation structure.
 */
static void TranslateFromObject(
    JNIEnv* env,
    jobject locationObject,
    FlpLocation& location) {
  location.size = sizeof(FlpLocation);
  location.flags = 0;

  jclass locationClass = env->GetObjectClass(locationObject);

  jmethodID getLatitude = env->GetMethodID(locationClass, "getLatitude", "()D");
  location.latitude = env->CallDoubleMethod(locationObject, getLatitude);
  jmethodID getLongitude = env->GetMethodID(locationClass, "getLongitude", "()D");
  location.longitude = env->CallDoubleMethod(locationObject, getLongitude);
  jmethodID getTime = env->GetMethodID(locationClass, "getTime", "()J");
  location.timestamp = env->CallLongMethod(locationObject, getTime);
  location.flags |= FLP_LOCATION_HAS_LAT_LONG;

  jmethodID hasAltitude = env->GetMethodID(locationClass, "hasAltitude", "()Z");
  if (env->CallBooleanMethod(locationObject, hasAltitude)) {
    jmethodID getAltitude = env->GetMethodID(locationClass, "getAltitude", "()D");
    location.altitude = env->CallDoubleMethod(locationObject, getAltitude);
    location.flags |= FLP_LOCATION_HAS_ALTITUDE;
  }

  jmethodID hasSpeed = env->GetMethodID(locationClass, "hasSpeed", "()Z");
  if (env->CallBooleanMethod(locationObject, hasSpeed)) {
    jmethodID getSpeed = env->GetMethodID(locationClass, "getSpeed", "()F");
    location.speed = env->CallFloatMethod(locationObject, getSpeed);
    location.flags |= FLP_LOCATION_HAS_SPEED;
  }

  jmethodID hasBearing = env->GetMethodID(locationClass, "hasBearing", "()Z");
  if (env->CallBooleanMethod(locationObject, hasBearing)) {
    jmethodID getBearing = env->GetMethodID(locationClass, "getBearing", "()F");
    location.bearing = env->CallFloatMethod(locationObject, getBearing);
    location.flags |= FLP_LOCATION_HAS_BEARING;
  }

  jmethodID hasAccuracy = env->GetMethodID(locationClass, "hasAccuracy", "()Z");
  if (env->CallBooleanMethod(locationObject, hasAccuracy)) {
    jmethodID getAccuracy = env->GetMethodID(
        locationClass,
        "getAccuracy",
        "()F"
        );
    location.accuracy = env->CallFloatMethod(locationObject, getAccuracy);
    location.flags |= FLP_LOCATION_HAS_ACCURACY;
  }

  // TODO: wire sources_used if Location class exposes them

  env->DeleteLocalRef(locationClass);
}

/*
 * Helper function to unwrap FlpBatchOptions from the Java Runtime calls.
 */
static void TranslateFromObject(
    JNIEnv* env,
    jobject batchOptionsObject,
    FlpBatchOptions& batchOptions) {
  jclass batchOptionsClass = env->GetObjectClass(batchOptionsObject);

  jmethodID getMaxPower = env->GetMethodID(
      batchOptionsClass,
      "getMaxPowerAllocationInMW",
      "()D"
      );
  batchOptions.max_power_allocation_mW = env->CallDoubleMethod(
      batchOptionsObject,
      getMaxPower
      );

  jmethodID getPeriod = env->GetMethodID(
      batchOptionsClass,
      "getPeriodInNS",
      "()J"
      );
  batchOptions.period_ns = env->CallLongMethod(batchOptionsObject, getPeriod);

  jmethodID getSourcesToUse = env->GetMethodID(
      batchOptionsClass,
      "getSourcesToUse",
      "()I"
      );
  batchOptions.sources_to_use = env->CallIntMethod(
      batchOptionsObject,
      getSourcesToUse
      );

  jmethodID getFlags = env->GetMethodID(batchOptionsClass, "getFlags", "()I");
  batchOptions.flags = env->CallIntMethod(batchOptionsObject, getFlags);

  env->DeleteLocalRef(batchOptionsClass);
}

/*
 * Helper function to unwrap Geofence structures from the Java Runtime calls.
 */
static void TranslateGeofenceFromGeofenceHardwareRequestParcelable(
    JNIEnv* env,
    jobject geofenceRequestObject,
    Geofence& geofence) {
  jclass geofenceRequestClass = env->GetObjectClass(geofenceRequestObject);

  jmethodID getId = env->GetMethodID(geofenceRequestClass, "getId", "()I");
  geofence.geofence_id = env->CallIntMethod(geofenceRequestObject, getId);

  jmethodID getType = env->GetMethodID(geofenceRequestClass, "getType", "()I");
  // this works because GeofenceHardwareRequest.java and fused_location.h have
  // the same notion of geofence types
  GeofenceType type = (GeofenceType)env->CallIntMethod(geofenceRequestObject, getType);
  if(type != TYPE_CIRCLE) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }
  geofence.data->type = type;
  GeofenceCircle& circle = geofence.data->geofence.circle;

  jmethodID getLatitude = env->GetMethodID(
      geofenceRequestClass,
      "getLatitude",
      "()D");
  circle.latitude = env->CallDoubleMethod(geofenceRequestObject, getLatitude);

  jmethodID getLongitude = env->GetMethodID(
      geofenceRequestClass,
      "getLongitude",
      "()D");
  circle.longitude = env->CallDoubleMethod(geofenceRequestObject, getLongitude);

  jmethodID getRadius = env->GetMethodID(geofenceRequestClass, "getRadius", "()D");
  circle.radius_m = env->CallDoubleMethod(geofenceRequestObject, getRadius);

  GeofenceOptions* options = geofence.options;
  jmethodID getMonitorTransitions = env->GetMethodID(
      geofenceRequestClass,
      "getMonitorTransitions",
      "()I");
  options->monitor_transitions = env->CallIntMethod(
      geofenceRequestObject,
      getMonitorTransitions);

  jmethodID getUnknownTimer = env->GetMethodID(
      geofenceRequestClass,
      "getUnknownTimer",
      "()I");
  options->unknown_timer_ms = env->CallIntMethod(geofenceRequestObject, getUnknownTimer);

  jmethodID getNotificationResponsiveness = env->GetMethodID(
      geofenceRequestClass,
      "getNotificationResponsiveness",
      "()I");
  options->notification_responsivenes_ms = env->CallIntMethod(
      geofenceRequestObject,
      getNotificationResponsiveness);

  jmethodID getLastTransition = env->GetMethodID(
      geofenceRequestClass,
      "getLastTransition",
      "()I");
  options->last_transition = env->CallIntMethod(geofenceRequestObject, getLastTransition);

  // TODO: set data.sources_to_use when available

  env->DeleteLocalRef(geofenceRequestClass);
}

/*
 * Helper function to transform FlpLocation into a java object.
 */
static void TranslateToObject(const FlpLocation* location, jobject& locationObject) {
  jclass locationClass = sCallbackEnv->FindClass(LOCATION_CLASS_NAME);
  jmethodID locationCtor = sCallbackEnv->GetMethodID(
      locationClass,
      "<init>",
      "(Ljava/lang/String;)V"
      );

  // the provider is set in the upper JVM layer
  locationObject = sCallbackEnv->NewObject(locationClass, locationCtor, NULL);
  jint flags = location->flags;

  // set the valid information in the object
  if (flags & FLP_LOCATION_HAS_LAT_LONG) {
    jmethodID setLatitude = sCallbackEnv->GetMethodID(
        locationClass,
        "setLatitude",
        "(D)V"
        );
    sCallbackEnv->CallVoidMethod(locationObject, setLatitude, location->latitude);

    jmethodID setLongitude = sCallbackEnv->GetMethodID(
        locationClass,
        "setLongitude",
        "(D)V"
        );
    sCallbackEnv->CallVoidMethod(
        locationObject,
        setLongitude,
        location->longitude
        );

    jmethodID setTime = sCallbackEnv->GetMethodID(
        locationClass,
        "setTime",
        "(J)V"
        );
    sCallbackEnv->CallVoidMethod(locationObject, setTime, location->timestamp);
  }

  if (flags & FLP_LOCATION_HAS_ALTITUDE) {
    jmethodID setAltitude = sCallbackEnv->GetMethodID(
        locationClass,
        "setAltitude",
        "(D)V"
        );
    sCallbackEnv->CallVoidMethod(locationObject, setAltitude, location->altitude);
  }

  if (flags & FLP_LOCATION_HAS_SPEED) {
    jmethodID setSpeed = sCallbackEnv->GetMethodID(
        locationClass,
        "setSpeed",
        "(F)V"
        );
    sCallbackEnv->CallVoidMethod(locationObject, setSpeed, location->speed);
  }

  if (flags & FLP_LOCATION_HAS_BEARING) {
    jmethodID setBearing = sCallbackEnv->GetMethodID(
        locationClass,
        "setBearing",
        "(F)V"
        );
    sCallbackEnv->CallVoidMethod(locationObject, setBearing, location->bearing);
  }

  if (flags & FLP_LOCATION_HAS_ACCURACY) {
    jmethodID setAccuracy = sCallbackEnv->GetMethodID(
        locationClass,
        "setAccuracy",
        "(F)V"
        );
    sCallbackEnv->CallVoidMethod(locationObject, setAccuracy, location->accuracy);
  }

  // TODO: wire FlpLocation::sources_used when needed

  sCallbackEnv->DeleteLocalRef(locationClass);
}

/*
 * Helper function to serialize FlpLocation structures.
 */
static void TranslateToObjectArray(
    int32_t locationsCount,
    FlpLocation** locations,
    jobjectArray& locationsArray) {
  jclass locationClass = sCallbackEnv->FindClass(LOCATION_CLASS_NAME);
  locationsArray = sCallbackEnv->NewObjectArray(
      locationsCount,
      locationClass,
      /* initialElement */ NULL
      );

  for (int i = 0; i < locationsCount; ++i) {
    jobject locationObject = NULL;
    TranslateToObject(locations[i], locationObject);
    sCallbackEnv->SetObjectArrayElement(locationsArray, i, locationObject);
    sCallbackEnv->DeleteLocalRef(locationObject);
  }

  sCallbackEnv->DeleteLocalRef(locationClass);
}

static void LocationCallback(int32_t locationsCount, FlpLocation** locations) {
  if(!IsValidCallbackThread()) {
    return;
  }

  if(locationsCount == 0 || locations == NULL) {
    ALOGE(
        "Invalid LocationCallback. Count: %d, Locations: %p",
        locationsCount,
        locations
        );
    return;
  }

  jobjectArray locationsArray = NULL;
  TranslateToObjectArray(locationsCount, locations, locationsArray);

  sCallbackEnv->CallVoidMethod(
      sCallbacksObj,
      sOnLocationReport,
      locationsArray
      );
  CheckExceptions(sCallbackEnv, __FUNCTION__);

  if(locationsArray != NULL) {
    sCallbackEnv->DeleteLocalRef(locationsArray);
  }
}

static void AcquireWakelock() {
  acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
}

static void ReleaseWakelock() {
  release_wake_lock(WAKE_LOCK_NAME);
}

FlpCallbacks sFlpCallbacks = {
  sizeof(FlpCallbacks),
  LocationCallback,
  AcquireWakelock,
  ReleaseWakelock,
  SetThreadEvent
};

static void ReportData(char* data, int length) {
  jstring stringData = NULL;

  if(length != 0 && data != NULL) {
    stringData = sCallbackEnv->NewString(reinterpret_cast<jchar*>(data), length);
  } else {
    ALOGE("Invalid ReportData callback. Length: %d, Data: %p", length, data);
    return;
  }

  sCallbackEnv->CallVoidMethod(sCallbacksObj, sOnDataReport, stringData);
  CheckExceptions(sCallbackEnv, __FUNCTION__);
}

FlpDiagnosticCallbacks sFlpDiagnosticCallbacks = {
  sizeof(FlpDiagnosticCallbacks),
  SetThreadEvent,
  ReportData
};

static void GeofenceTransitionCallback(
    int32_t geofenceId,
    FlpLocation* location,
    int32_t transition,
    FlpUtcTime timestamp,
    uint32_t sourcesUsed
    ) {
  if(!IsValidCallbackThread()) {
    return;
  }

  if(location == NULL) {
    ALOGE("GeofenceTransition received with invalid location: %p", location);
    return;
  }

  jobject locationObject = NULL;
  TranslateToObject(location, locationObject);

  sCallbackEnv->CallVoidMethod(
      sCallbacksObj,
      sOnGeofenceTransition,
      geofenceId,
      locationObject,
      transition,
      timestamp,
      sourcesUsed
      );
  CheckExceptions(sCallbackEnv, __FUNCTION__);

  if(locationObject != NULL) {
    sCallbackEnv->DeleteLocalRef(locationObject);
  }
}

static void GeofenceMonitorStatusCallback(
    int32_t status,
    uint32_t source,
    FlpLocation* lastLocation) {
  if(!IsValidCallbackThread()) {
    return;
  }

  jobject locationObject = NULL;
  if(lastLocation != NULL) {
    TranslateToObject(lastLocation, locationObject);
  }

  sCallbackEnv->CallVoidMethod(
      sCallbacksObj,
      sOnGeofenceMonitorStatus,
      status,
      source,
      locationObject
      );
  CheckExceptions(sCallbackEnv, __FUNCTION__);

  if(locationObject != NULL) {
    sCallbackEnv->DeleteLocalRef(locationObject);
  }
}

static void GeofenceAddCallback(int32_t geofenceId, int32_t result) {
  if(!IsValidCallbackThread()) {
    return;
  }

  sCallbackEnv->CallVoidMethod(sCallbacksObj, sOnGeofenceAdd, geofenceId, result);
  CheckExceptions(sCallbackEnv, __FUNCTION__);
}

static void GeofenceRemoveCallback(int32_t geofenceId, int32_t result) {
  if(!IsValidCallbackThread()) {
    return;
  }

  sCallbackEnv->CallVoidMethod(
      sCallbacksObj,
      sOnGeofenceRemove,
      geofenceId,
      result
      );
  CheckExceptions(sCallbackEnv, __FUNCTION__);
}

static void GeofencePauseCallback(int32_t geofenceId, int32_t result) {
  if(!IsValidCallbackThread()) {
    return;
  }

  sCallbackEnv->CallVoidMethod(
      sCallbacksObj,
      sOnGeofencePause,
      geofenceId,
      result
      );
  CheckExceptions(sCallbackEnv, __FUNCTION__);
}

static void GeofenceResumeCallback(int32_t geofenceId, int32_t result) {
  if(!IsValidCallbackThread()) {
    return;
  }

  sCallbackEnv->CallVoidMethod(
      sCallbacksObj,
      sOnGeofenceResume,
      geofenceId,
      result
      );
  CheckExceptions(sCallbackEnv, __FUNCTION__);
}

FlpGeofenceCallbacks sFlpGeofenceCallbacks = {
  sizeof(FlpGeofenceCallbacks),
  GeofenceTransitionCallback,
  GeofenceMonitorStatusCallback,
  GeofenceAddCallback,
  GeofenceRemoveCallback,
  GeofencePauseCallback,
  GeofenceResumeCallback,
  SetThreadEvent
};

/*
 * Initializes the Fused Location Provider in the native side. It ensures that
 * the Flp interfaces are initialized properly.
 */
static void Init(JNIEnv* env, jobject obj) {
  if(sHardwareDevice != NULL) {
    ALOGD("Hardware Device already opened.");
    return;
  }

  const hw_module_t* module = NULL;
  int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, &module);
  if(err != 0) {
    ALOGE("Error hw_get_module '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
    return;
  }

  err = module->methods->open(
        module,
        FUSED_LOCATION_HARDWARE_MODULE_ID, &sHardwareDevice);
  if(err != 0) {
    ALOGE("Error opening device '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
    return;
  }

  sFlpInterface = NULL;
  flp_device_t* flp_device = reinterpret_cast<flp_device_t*>(sHardwareDevice);
  sFlpInterface = flp_device->get_flp_interface(flp_device);

  if(sFlpInterface != NULL) {
    sFlpDiagnosticInterface = reinterpret_cast<const FlpDiagnosticInterface*>(
        sFlpInterface->get_extension(FLP_DIAGNOSTIC_INTERFACE)
        );

    sFlpGeofencingInterface = reinterpret_cast<const FlpGeofencingInterface*>(
        sFlpInterface->get_extension(FLP_GEOFENCING_INTERFACE)
        );

    sFlpDeviceContextInterface = reinterpret_cast<const FlpDeviceContextInterface*>(
        sFlpInterface->get_extension(FLP_DEVICE_CONTEXT_INTERFACE)
        );
  }

  if(sCallbacksObj == NULL) {
    sCallbacksObj = env->NewGlobalRef(obj);
  }

  // initialize the Flp interfaces
  if(sFlpInterface == NULL || sFlpInterface->init(&sFlpCallbacks) != 0) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  if(sFlpDiagnosticInterface != NULL) {
    sFlpDiagnosticInterface->init(&sFlpDiagnosticCallbacks);
  }

  if(sFlpGeofencingInterface != NULL) {
    sFlpGeofencingInterface->init(&sFlpGeofenceCallbacks);
  }

  // TODO: inject any device context if when needed
}

static jboolean IsSupported(JNIEnv* env, jclass clazz) {
  return sFlpInterface != NULL;
}

static jint GetBatchSize(JNIEnv* env, jobject object) {
  if(sFlpInterface == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  return sFlpInterface->get_batch_size();
}

static void StartBatching(
    JNIEnv* env,
    jobject object,
    jint id,
    jobject optionsObject) {
  if(sFlpInterface == NULL || optionsObject == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  FlpBatchOptions options;
  TranslateFromObject(env, optionsObject, options);
  int result = sFlpInterface->start_batching(id, &options);
  ThrowOnError(env, result, __FUNCTION__);
}

static void UpdateBatchingOptions(
    JNIEnv* env,
    jobject object,
    jint id,
    jobject optionsObject) {
  if(sFlpInterface == NULL || optionsObject == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  FlpBatchOptions options;
  TranslateFromObject(env, optionsObject, options);
  int result = sFlpInterface->update_batching_options(id, &options);
  ThrowOnError(env, result, __FUNCTION__);
}

static void StopBatching(JNIEnv* env, jobject object, jint id) {
  if(sFlpInterface == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  sFlpInterface->stop_batching(id);
}

static void Cleanup(JNIEnv* env, jobject object) {
  if(sFlpInterface == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  sFlpInterface->cleanup();

  if(sCallbacksObj != NULL) {
    env->DeleteGlobalRef(sCallbacksObj);
    sCallbacksObj = NULL;
  }

  sFlpInterface = NULL;
  sFlpDiagnosticInterface = NULL;
  sFlpDeviceContextInterface = NULL;
  sFlpGeofencingInterface = NULL;

  if(sHardwareDevice != NULL) {
    sHardwareDevice->close(sHardwareDevice);
    sHardwareDevice = NULL;
  }
}

static void GetBatchedLocation(JNIEnv* env, jobject object, jint lastNLocations) {
  if(sFlpInterface == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  sFlpInterface->get_batched_location(lastNLocations);
}

static void InjectLocation(JNIEnv* env, jobject object, jobject locationObject) {
  if(locationObject == NULL) {
    ALOGE("Invalid location for injection: %p", locationObject);
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  if(sFlpInterface == NULL) {
    // there is no listener, bail
    return;
  }

  FlpLocation location;
  TranslateFromObject(env, locationObject, location);
  int result = sFlpInterface->inject_location(&location);
  if (result != FLP_RESULT_SUCCESS) {
    // do not throw but log, this operation should be fire and forget
    ALOGE("Error %d in '%s'", result, __FUNCTION__);
  }
}

static jboolean IsDiagnosticSupported() {
  return sFlpDiagnosticInterface != NULL;
}

static void InjectDiagnosticData(JNIEnv* env, jobject object, jstring stringData) {
  if(stringData == NULL) {
    ALOGE("Invalid diagnostic data for injection: %p", stringData);
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  if(sFlpDiagnosticInterface == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  int length = env->GetStringLength(stringData);
  const jchar* data = env->GetStringChars(stringData, /* isCopy */ NULL);
  if(data == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  int result = sFlpDiagnosticInterface->inject_data((char*) data, length);
  ThrowOnError(env, result, __FUNCTION__);
}

static jboolean IsDeviceContextSupported() {
  return sFlpDeviceContextInterface != NULL;
}

static void InjectDeviceContext(JNIEnv* env, jobject object, jint enabledMask) {
  if(sFlpDeviceContextInterface == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  int result = sFlpDeviceContextInterface->inject_device_context(enabledMask);
  ThrowOnError(env, result, __FUNCTION__);
}

static jboolean IsGeofencingSupported() {
  return sFlpGeofencingInterface != NULL;
}

static void AddGeofences(
    JNIEnv* env,
    jobject object,
    jobjectArray geofenceRequestsArray) {
  if(geofenceRequestsArray == NULL) {
    ALOGE("Invalid Geofences to add: %p", geofenceRequestsArray);
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  if (sFlpGeofencingInterface == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  jint geofenceRequestsCount = env->GetArrayLength(geofenceRequestsArray);
  if(geofenceRequestsCount == 0) {
    return;
  }

  Geofence* geofences = new Geofence[geofenceRequestsCount];
  if (geofences == NULL) {
    ThrowOnError(env, FLP_RESULT_INSUFFICIENT_MEMORY, __FUNCTION__);
  }

  for (int i = 0; i < geofenceRequestsCount; ++i) {
    geofences[i].data = new GeofenceData();
    geofences[i].options = new GeofenceOptions();
    jobject geofenceObject = env->GetObjectArrayElement(geofenceRequestsArray, i);

    TranslateGeofenceFromGeofenceHardwareRequestParcelable(env, geofenceObject, geofences[i]);
    env->DeleteLocalRef(geofenceObject);
  }

  sFlpGeofencingInterface->add_geofences(geofenceRequestsCount, &geofences);
  if (geofences != NULL) {
    for(int i = 0; i < geofenceRequestsCount; ++i) {
      delete geofences[i].data;
      delete geofences[i].options;
    }
    delete[] geofences;
  }
}

static void PauseGeofence(JNIEnv* env, jobject object, jint geofenceId) {
  if(sFlpGeofencingInterface == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  sFlpGeofencingInterface->pause_geofence(geofenceId);
}

static void ResumeGeofence(
    JNIEnv* env,
    jobject object,
    jint geofenceId,
    jint monitorTransitions) {
  if(sFlpGeofencingInterface == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  sFlpGeofencingInterface->resume_geofence(geofenceId, monitorTransitions);
}

static void ModifyGeofenceOption(
    JNIEnv* env,
    jobject object,
    jint geofenceId,
    jint lastTransition,
    jint monitorTransitions,
    jint notificationResponsiveness,
    jint unknownTimer,
    jint sourcesToUse) {
  if(sFlpGeofencingInterface == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  GeofenceOptions options = {
      lastTransition,
      monitorTransitions,
      notificationResponsiveness,
      unknownTimer,
      (uint32_t)sourcesToUse
  };

  sFlpGeofencingInterface->modify_geofence_option(geofenceId, &options);
}

static void RemoveGeofences(
    JNIEnv* env,
    jobject object,
    jintArray geofenceIdsArray) {
  if(sFlpGeofencingInterface == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  jsize geofenceIdsCount = env->GetArrayLength(geofenceIdsArray);
  jint* geofenceIds = env->GetIntArrayElements(geofenceIdsArray, /* isCopy */ NULL);
  if(geofenceIds == NULL) {
    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
  }

  sFlpGeofencingInterface->remove_geofences(geofenceIdsCount, geofenceIds);
  env->ReleaseIntArrayElements(geofenceIdsArray, geofenceIds, 0 /*mode*/);
}

static JNINativeMethod sMethods[] = {
  //{"name", "signature", functionPointer }
  {"nativeClassInit", "()V", reinterpret_cast<void*>(ClassInit)},
  {"nativeInit", "()V", reinterpret_cast<void*>(Init)},
  {"nativeCleanup", "()V", reinterpret_cast<void*>(Cleanup)},
  {"nativeIsSupported", "()Z", reinterpret_cast<void*>(IsSupported)},
  {"nativeGetBatchSize", "()I", reinterpret_cast<void*>(GetBatchSize)},
  {"nativeStartBatching",
        "(ILandroid/location/FusedBatchOptions;)V",
        reinterpret_cast<void*>(StartBatching)},
  {"nativeUpdateBatchingOptions",
        "(ILandroid/location/FusedBatchOptions;)V",
        reinterpret_cast<void*>(UpdateBatchingOptions)},
  {"nativeStopBatching", "(I)V", reinterpret_cast<void*>(StopBatching)},
  {"nativeRequestBatchedLocation",
        "(I)V",
        reinterpret_cast<void*>(GetBatchedLocation)},
  {"nativeInjectLocation",
        "(Landroid/location/Location;)V",
        reinterpret_cast<void*>(InjectLocation)},
  {"nativeIsDiagnosticSupported",
        "()Z",
        reinterpret_cast<void*>(IsDiagnosticSupported)},
  {"nativeInjectDiagnosticData",
        "(Ljava/lang/String;)V",
        reinterpret_cast<void*>(InjectDiagnosticData)},
  {"nativeIsDeviceContextSupported",
        "()Z",
        reinterpret_cast<void*>(IsDeviceContextSupported)},
  {"nativeInjectDeviceContext",
        "(I)V",
        reinterpret_cast<void*>(InjectDeviceContext)},
  {"nativeIsGeofencingSupported",
        "()Z",
        reinterpret_cast<void*>(IsGeofencingSupported)},
  {"nativeAddGeofences",
        "([Landroid/hardware/location/GeofenceHardwareRequestParcelable;)V",
        reinterpret_cast<void*>(AddGeofences)},
  {"nativePauseGeofence", "(I)V", reinterpret_cast<void*>(PauseGeofence)},
  {"nativeResumeGeofence", "(II)V", reinterpret_cast<void*>(ResumeGeofence)},
  {"nativeModifyGeofenceOption",
        "(IIIIII)V",
        reinterpret_cast<void*>(ModifyGeofenceOption)},
  {"nativeRemoveGeofences", "([I)V", reinterpret_cast<void*>(RemoveGeofences)}
};

/*
 * Registration method invoked on JNI Load.
 */
int register_android_server_location_FlpHardwareProvider(JNIEnv* env) {
  return jniRegisterNativeMethods(
      env,
      "com/android/server/location/FlpHardwareProvider",
      sMethods,
      NELEM(sMethods)
      );
}

} /* name-space Android */
