11af4b0280af406cfc7eb46810f6b76e57b983e11destradaa/*
21af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Copyright (C) 2013 The Android Open Source Project
31af4b0280af406cfc7eb46810f6b76e57b983e11destradaa *
41af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Licensed under the Apache License, Version 2.0 (the "License");
51af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * you may not use this file except in compliance with the License.
61af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * You may obtain a copy of the license at
71af4b0280af406cfc7eb46810f6b76e57b983e11destradaa *
81af4b0280af406cfc7eb46810f6b76e57b983e11destradaa *      http://www.apache.org/license/LICENSE-2.0
91af4b0280af406cfc7eb46810f6b76e57b983e11destradaa *
101af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Unless required by applicable law or agreed to in writing, software
111af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * distributed under the License is distributed on an "AS IS" BASIS,
121af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * See the License for the specific language governing permissions and
141af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * limitations under the license.
151af4b0280af406cfc7eb46810f6b76e57b983e11destradaa */
161af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
17264705a3f6a3220eb293898cf190eaed55e26970destradaa#define LOG_TAG "FlpHardwareProvider"
181af4b0280af406cfc7eb46810f6b76e57b983e11destradaa#define LOG_NDEBUG  0
191af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
201af4b0280af406cfc7eb46810f6b76e57b983e11destradaa#define WAKE_LOCK_NAME  "FLP"
211af4b0280af406cfc7eb46810f6b76e57b983e11destradaa#define LOCATION_CLASS_NAME "android/location/Location"
221af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
231af4b0280af406cfc7eb46810f6b76e57b983e11destradaa#include "jni.h"
241af4b0280af406cfc7eb46810f6b76e57b983e11destradaa#include "JNIHelp.h"
251af4b0280af406cfc7eb46810f6b76e57b983e11destradaa#include "android_runtime/AndroidRuntime.h"
2687eac99a21772ae56018cb81db6966557b459554Ruben Brunk#include "android_runtime/Log.h"
271af4b0280af406cfc7eb46810f6b76e57b983e11destradaa#include "hardware/fused_location.h"
281af4b0280af406cfc7eb46810f6b76e57b983e11destradaa#include "hardware_legacy/power.h"
291af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
301af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jobject sCallbacksObj = NULL;
311af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic JNIEnv *sCallbackEnv = NULL;
321af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic hw_device_t* sHardwareDevice = NULL;
331af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
341af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jmethodID sOnLocationReport = NULL;
351af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jmethodID sOnDataReport = NULL;
361af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jmethodID sOnGeofenceTransition = NULL;
371af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jmethodID sOnGeofenceMonitorStatus = NULL;
381af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jmethodID sOnGeofenceAdd = NULL;
391af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jmethodID sOnGeofenceRemove = NULL;
401af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jmethodID sOnGeofencePause = NULL;
411af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jmethodID sOnGeofenceResume = NULL;
421af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
431af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic const FlpLocationInterface* sFlpInterface = NULL;
441af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic const FlpDiagnosticInterface* sFlpDiagnosticInterface = NULL;
451af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic const FlpGeofencingInterface* sFlpGeofencingInterface = NULL;
461af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic const FlpDeviceContextInterface* sFlpDeviceContextInterface = NULL;
471af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
481af4b0280af406cfc7eb46810f6b76e57b983e11destradaanamespace android {
491af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
501af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic inline void CheckExceptions(JNIEnv* env, const char* methodName) {
511af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(!env->ExceptionCheck()) {
521af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
531af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
541af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
551af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  ALOGE("An exception was thrown by '%s'.", methodName);
561af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  LOGE_EX(env);
571af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  env->ExceptionClear();
581af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
591af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
601af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic inline void ThrowOnError(
611af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    JNIEnv* env,
621af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    int resultCode,
631af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    const char* methodName) {
641af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(resultCode == FLP_RESULT_SUCCESS) {
651af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
661af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
671af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
681af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  ALOGE("Error %d in '%s'", resultCode, methodName);
69264705a3f6a3220eb293898cf190eaed55e26970destradaa  env->FatalError(methodName);
701af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
711af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
721af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic bool IsValidCallbackThread() {
731af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  JNIEnv* env = AndroidRuntime::getJNIEnv();
741af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
751af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sCallbackEnv == NULL || sCallbackEnv != env) {
761af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ALOGE("CallbackThread check fail: env=%p, expected=%p", env, sCallbackEnv);
771af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return false;
781af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
791af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
801af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  return true;
811af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
821af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
831af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic int SetThreadEvent(ThreadEvent event) {
841af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  JavaVM* javaVm = AndroidRuntime::getJavaVM();
851af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
861af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  switch(event) {
871af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    case ASSOCIATE_JVM:
881af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    {
891af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      if(sCallbackEnv != NULL) {
901af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        ALOGE(
911af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            "Attempted to associate callback in '%s'. Callback already associated.",
921af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            __FUNCTION__
931af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            );
941af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        return FLP_RESULT_ERROR;
951af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      }
961af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
971af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      JavaVMAttachArgs args = {
981af4b0280af406cfc7eb46810f6b76e57b983e11destradaa          JNI_VERSION_1_6,
991af4b0280af406cfc7eb46810f6b76e57b983e11destradaa          "FLP Service Callback Thread",
1001af4b0280af406cfc7eb46810f6b76e57b983e11destradaa          /* group */ NULL
1011af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      };
1021af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1031af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      jint attachResult = javaVm->AttachCurrentThread(&sCallbackEnv, &args);
1041af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      if (attachResult != 0) {
1051af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        ALOGE("Callback thread attachment error: %d", attachResult);
1061af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        return FLP_RESULT_ERROR;
1071af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      }
1081af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1091af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      ALOGV("Callback thread attached: %p", sCallbackEnv);
1101af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      break;
1111af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
1121af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    case DISASSOCIATE_JVM:
1131af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    {
1141af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      if (!IsValidCallbackThread()) {
1151af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        ALOGE(
1161af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            "Attempted to dissasociate an unnownk callback thread : '%s'.",
1171af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            __FUNCTION__
1181af4b0280af406cfc7eb46810f6b76e57b983e11destradaa            );
1191af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        return FLP_RESULT_ERROR;
1201af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      }
1211af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1221af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      if (javaVm->DetachCurrentThread() != 0) {
1231af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        return FLP_RESULT_ERROR;
1241af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      }
1251af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1261af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sCallbackEnv = NULL;
1271af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      break;
1281af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    }
1291af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    default:
1301af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      ALOGE("Invalid ThreadEvent request %d", event);
1311af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      return FLP_RESULT_ERROR;
1321af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
1331af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1341af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  return FLP_RESULT_SUCCESS;
1351af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
1361af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1371af4b0280af406cfc7eb46810f6b76e57b983e11destradaa/*
1381af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Initializes the FlpHardwareProvider class from the native side by opening
1391af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * the HW module and obtaining the proper interfaces.
1401af4b0280af406cfc7eb46810f6b76e57b983e11destradaa */
1411af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void ClassInit(JNIEnv* env, jclass clazz) {
1421af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  // get references to the Java provider methods
1431af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sOnLocationReport = env->GetMethodID(
1441af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      clazz,
1451af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "onLocationReport",
1461af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "([Landroid/location/Location;)V");
1471af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sOnDataReport = env->GetMethodID(
1481af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      clazz,
1491af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "onDataReport",
1501af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "(Ljava/lang/String;)V"
1511af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
1521af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sOnGeofenceTransition = env->GetMethodID(
1531af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      clazz,
1541af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "onGeofenceTransition",
1551af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "(ILandroid/location/Location;IJI)V"
1561af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
1571af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sOnGeofenceMonitorStatus = env->GetMethodID(
1581af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      clazz,
1591af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "onGeofenceMonitorStatus",
1601af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "(IILandroid/location/Location;)V"
1611af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
1621af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sOnGeofenceAdd = env->GetMethodID(clazz, "onGeofenceAdd", "(II)V");
1631af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sOnGeofenceRemove = env->GetMethodID(clazz, "onGeofenceRemove", "(II)V");
1641af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sOnGeofencePause = env->GetMethodID(clazz, "onGeofencePause", "(II)V");
1651af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sOnGeofenceResume = env->GetMethodID(clazz, "onGeofenceResume", "(II)V");
1661af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
1671af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1681af4b0280af406cfc7eb46810f6b76e57b983e11destradaa/*
1691af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Helper function to unwrap a java object back into a FlpLocation structure.
1701af4b0280af406cfc7eb46810f6b76e57b983e11destradaa */
1711af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void TranslateFromObject(
1721af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    JNIEnv* env,
1731af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jobject locationObject,
1741af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    FlpLocation& location) {
1751af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  location.size = sizeof(FlpLocation);
1761af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  location.flags = 0;
1771af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1781af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jclass locationClass = env->GetObjectClass(locationObject);
1791af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1801af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jmethodID getLatitude = env->GetMethodID(locationClass, "getLatitude", "()D");
1811af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  location.latitude = env->CallDoubleMethod(locationObject, getLatitude);
1821af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jmethodID getLongitude = env->GetMethodID(locationClass, "getLongitude", "()D");
1831af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  location.longitude = env->CallDoubleMethod(locationObject, getLongitude);
1841af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jmethodID getTime = env->GetMethodID(locationClass, "getTime", "()J");
1851af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  location.timestamp = env->CallLongMethod(locationObject, getTime);
1861af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  location.flags |= FLP_LOCATION_HAS_LAT_LONG;
1871af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1881af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jmethodID hasAltitude = env->GetMethodID(locationClass, "hasAltitude", "()Z");
1891af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if (env->CallBooleanMethod(locationObject, hasAltitude)) {
1901af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jmethodID getAltitude = env->GetMethodID(locationClass, "getAltitude", "()D");
1911af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    location.altitude = env->CallDoubleMethod(locationObject, getAltitude);
1921af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    location.flags |= FLP_LOCATION_HAS_ALTITUDE;
1931af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
1941af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
1951af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jmethodID hasSpeed = env->GetMethodID(locationClass, "hasSpeed", "()Z");
1961af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if (env->CallBooleanMethod(locationObject, hasSpeed)) {
1971af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jmethodID getSpeed = env->GetMethodID(locationClass, "getSpeed", "()F");
1981af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    location.speed = env->CallFloatMethod(locationObject, getSpeed);
1991af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    location.flags |= FLP_LOCATION_HAS_SPEED;
2001af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
2011af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
2021af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jmethodID hasBearing = env->GetMethodID(locationClass, "hasBearing", "()Z");
2031af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if (env->CallBooleanMethod(locationObject, hasBearing)) {
2041af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jmethodID getBearing = env->GetMethodID(locationClass, "getBearing", "()F");
2051af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    location.bearing = env->CallFloatMethod(locationObject, getBearing);
2061af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    location.flags |= FLP_LOCATION_HAS_BEARING;
2071af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
2081af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
2091af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jmethodID hasAccuracy = env->GetMethodID(locationClass, "hasAccuracy", "()Z");
2101af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if (env->CallBooleanMethod(locationObject, hasAccuracy)) {
2111af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jmethodID getAccuracy = env->GetMethodID(
2121af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        locationClass,
2131af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "getAccuracy",
2141af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "()F"
2151af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        );
2161af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    location.accuracy = env->CallFloatMethod(locationObject, getAccuracy);
2171af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    location.flags |= FLP_LOCATION_HAS_ACCURACY;
2181af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
2191af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
2201af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  // TODO: wire sources_used if Location class exposes them
221b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa
222b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa  env->DeleteLocalRef(locationClass);
2231af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
2241af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
2251af4b0280af406cfc7eb46810f6b76e57b983e11destradaa/*
2261af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Helper function to unwrap FlpBatchOptions from the Java Runtime calls.
2271af4b0280af406cfc7eb46810f6b76e57b983e11destradaa */
2281af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void TranslateFromObject(
2291af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    JNIEnv* env,
2301af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jobject batchOptionsObject,
2311af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    FlpBatchOptions& batchOptions) {
2321af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jclass batchOptionsClass = env->GetObjectClass(batchOptionsObject);
2331af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
2341af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jmethodID getMaxPower = env->GetMethodID(
2351af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      batchOptionsClass,
2361af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "getMaxPowerAllocationInMW",
2371af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "()D"
2381af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
2391af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  batchOptions.max_power_allocation_mW = env->CallDoubleMethod(
2401af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      batchOptionsObject,
2411af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      getMaxPower
2421af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
2431af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
2441af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jmethodID getPeriod = env->GetMethodID(
2451af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      batchOptionsClass,
2461af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "getPeriodInNS",
2471af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "()J"
2481af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
2491af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  batchOptions.period_ns = env->CallLongMethod(batchOptionsObject, getPeriod);
2501af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
2511af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jmethodID getSourcesToUse = env->GetMethodID(
2521af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      batchOptionsClass,
2531af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "getSourcesToUse",
2541af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "()I"
2551af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
2561af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  batchOptions.sources_to_use = env->CallIntMethod(
2571af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      batchOptionsObject,
2581af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      getSourcesToUse
2591af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
2601af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
2611af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jmethodID getFlags = env->GetMethodID(batchOptionsClass, "getFlags", "()I");
2621af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  batchOptions.flags = env->CallIntMethod(batchOptionsObject, getFlags);
263b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa
264b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa  env->DeleteLocalRef(batchOptionsClass);
2651af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
2661af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
2671af4b0280af406cfc7eb46810f6b76e57b983e11destradaa/*
2680682809ad08db284d7110aab44108d5e9c310e6bdestradaa * Helper function to unwrap Geofence structures from the Java Runtime calls.
2690682809ad08db284d7110aab44108d5e9c310e6bdestradaa */
2700682809ad08db284d7110aab44108d5e9c310e6bdestradaastatic void TranslateGeofenceFromGeofenceHardwareRequestParcelable(
2710682809ad08db284d7110aab44108d5e9c310e6bdestradaa    JNIEnv* env,
2720682809ad08db284d7110aab44108d5e9c310e6bdestradaa    jobject geofenceRequestObject,
2730682809ad08db284d7110aab44108d5e9c310e6bdestradaa    Geofence& geofence) {
2740682809ad08db284d7110aab44108d5e9c310e6bdestradaa  jclass geofenceRequestClass = env->GetObjectClass(geofenceRequestObject);
2750682809ad08db284d7110aab44108d5e9c310e6bdestradaa
2760682809ad08db284d7110aab44108d5e9c310e6bdestradaa  jmethodID getId = env->GetMethodID(geofenceRequestClass, "getId", "()I");
2770682809ad08db284d7110aab44108d5e9c310e6bdestradaa  geofence.geofence_id = env->CallIntMethod(geofenceRequestObject, getId);
2780682809ad08db284d7110aab44108d5e9c310e6bdestradaa
2790682809ad08db284d7110aab44108d5e9c310e6bdestradaa  jmethodID getType = env->GetMethodID(geofenceRequestClass, "getType", "()I");
2800682809ad08db284d7110aab44108d5e9c310e6bdestradaa  // this works because GeofenceHardwareRequest.java and fused_location.h have
2810682809ad08db284d7110aab44108d5e9c310e6bdestradaa  // the same notion of geofence types
2820682809ad08db284d7110aab44108d5e9c310e6bdestradaa  GeofenceType type = (GeofenceType)env->CallIntMethod(geofenceRequestObject, getType);
2830682809ad08db284d7110aab44108d5e9c310e6bdestradaa  if(type != TYPE_CIRCLE) {
2840682809ad08db284d7110aab44108d5e9c310e6bdestradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
2850682809ad08db284d7110aab44108d5e9c310e6bdestradaa  }
2860682809ad08db284d7110aab44108d5e9c310e6bdestradaa  geofence.data->type = type;
2870682809ad08db284d7110aab44108d5e9c310e6bdestradaa  GeofenceCircle& circle = geofence.data->geofence.circle;
2880682809ad08db284d7110aab44108d5e9c310e6bdestradaa
2890682809ad08db284d7110aab44108d5e9c310e6bdestradaa  jmethodID getLatitude = env->GetMethodID(
2900682809ad08db284d7110aab44108d5e9c310e6bdestradaa      geofenceRequestClass,
2910682809ad08db284d7110aab44108d5e9c310e6bdestradaa      "getLatitude",
2920682809ad08db284d7110aab44108d5e9c310e6bdestradaa      "()D");
2930682809ad08db284d7110aab44108d5e9c310e6bdestradaa  circle.latitude = env->CallDoubleMethod(geofenceRequestObject, getLatitude);
2940682809ad08db284d7110aab44108d5e9c310e6bdestradaa
2950682809ad08db284d7110aab44108d5e9c310e6bdestradaa  jmethodID getLongitude = env->GetMethodID(
2960682809ad08db284d7110aab44108d5e9c310e6bdestradaa      geofenceRequestClass,
2970682809ad08db284d7110aab44108d5e9c310e6bdestradaa      "getLongitude",
2980682809ad08db284d7110aab44108d5e9c310e6bdestradaa      "()D");
2990682809ad08db284d7110aab44108d5e9c310e6bdestradaa  circle.longitude = env->CallDoubleMethod(geofenceRequestObject, getLongitude);
3000682809ad08db284d7110aab44108d5e9c310e6bdestradaa
3010682809ad08db284d7110aab44108d5e9c310e6bdestradaa  jmethodID getRadius = env->GetMethodID(geofenceRequestClass, "getRadius", "()D");
3020682809ad08db284d7110aab44108d5e9c310e6bdestradaa  circle.radius_m = env->CallDoubleMethod(geofenceRequestObject, getRadius);
3030682809ad08db284d7110aab44108d5e9c310e6bdestradaa
3040682809ad08db284d7110aab44108d5e9c310e6bdestradaa  GeofenceOptions* options = geofence.options;
3050682809ad08db284d7110aab44108d5e9c310e6bdestradaa  jmethodID getMonitorTransitions = env->GetMethodID(
3060682809ad08db284d7110aab44108d5e9c310e6bdestradaa      geofenceRequestClass,
3070682809ad08db284d7110aab44108d5e9c310e6bdestradaa      "getMonitorTransitions",
3080682809ad08db284d7110aab44108d5e9c310e6bdestradaa      "()I");
3090682809ad08db284d7110aab44108d5e9c310e6bdestradaa  options->monitor_transitions = env->CallIntMethod(
3100682809ad08db284d7110aab44108d5e9c310e6bdestradaa      geofenceRequestObject,
3110682809ad08db284d7110aab44108d5e9c310e6bdestradaa      getMonitorTransitions);
3120682809ad08db284d7110aab44108d5e9c310e6bdestradaa
3130682809ad08db284d7110aab44108d5e9c310e6bdestradaa  jmethodID getUnknownTimer = env->GetMethodID(
3140682809ad08db284d7110aab44108d5e9c310e6bdestradaa      geofenceRequestClass,
3150682809ad08db284d7110aab44108d5e9c310e6bdestradaa      "getUnknownTimer",
3160682809ad08db284d7110aab44108d5e9c310e6bdestradaa      "()I");
3170682809ad08db284d7110aab44108d5e9c310e6bdestradaa  options->unknown_timer_ms = env->CallIntMethod(geofenceRequestObject, getUnknownTimer);
3180682809ad08db284d7110aab44108d5e9c310e6bdestradaa
3190682809ad08db284d7110aab44108d5e9c310e6bdestradaa  jmethodID getNotificationResponsiveness = env->GetMethodID(
3200682809ad08db284d7110aab44108d5e9c310e6bdestradaa      geofenceRequestClass,
3210682809ad08db284d7110aab44108d5e9c310e6bdestradaa      "getNotificationResponsiveness",
322839904eed81bf9cd87c27de49903dddb64ae3937destradaa      "()I");
3230682809ad08db284d7110aab44108d5e9c310e6bdestradaa  options->notification_responsivenes_ms = env->CallIntMethod(
3240682809ad08db284d7110aab44108d5e9c310e6bdestradaa      geofenceRequestObject,
3250682809ad08db284d7110aab44108d5e9c310e6bdestradaa      getNotificationResponsiveness);
3260682809ad08db284d7110aab44108d5e9c310e6bdestradaa
3270682809ad08db284d7110aab44108d5e9c310e6bdestradaa  jmethodID getLastTransition = env->GetMethodID(
3280682809ad08db284d7110aab44108d5e9c310e6bdestradaa      geofenceRequestClass,
3290682809ad08db284d7110aab44108d5e9c310e6bdestradaa      "getLastTransition",
3300682809ad08db284d7110aab44108d5e9c310e6bdestradaa      "()I");
3310682809ad08db284d7110aab44108d5e9c310e6bdestradaa  options->last_transition = env->CallIntMethod(geofenceRequestObject, getLastTransition);
3320682809ad08db284d7110aab44108d5e9c310e6bdestradaa
3330682809ad08db284d7110aab44108d5e9c310e6bdestradaa  // TODO: set data.sources_to_use when available
334b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa
335b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa  env->DeleteLocalRef(geofenceRequestClass);
3360682809ad08db284d7110aab44108d5e9c310e6bdestradaa}
3370682809ad08db284d7110aab44108d5e9c310e6bdestradaa
3380682809ad08db284d7110aab44108d5e9c310e6bdestradaa/*
3391af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Helper function to transform FlpLocation into a java object.
3401af4b0280af406cfc7eb46810f6b76e57b983e11destradaa */
3411af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void TranslateToObject(const FlpLocation* location, jobject& locationObject) {
3421af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jclass locationClass = sCallbackEnv->FindClass(LOCATION_CLASS_NAME);
3431af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jmethodID locationCtor = sCallbackEnv->GetMethodID(
3441af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      locationClass,
3451af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "<init>",
3461af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "(Ljava/lang/String;)V"
3471af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
3481af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
3491af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  // the provider is set in the upper JVM layer
3501af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  locationObject = sCallbackEnv->NewObject(locationClass, locationCtor, NULL);
3511af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jint flags = location->flags;
3521af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
3531af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  // set the valid information in the object
3541af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if (flags & FLP_LOCATION_HAS_LAT_LONG) {
3551af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jmethodID setLatitude = sCallbackEnv->GetMethodID(
3561af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        locationClass,
3571af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "setLatitude",
3581af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "(D)V"
3591af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        );
3601af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sCallbackEnv->CallVoidMethod(locationObject, setLatitude, location->latitude);
3611af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
3621af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jmethodID setLongitude = sCallbackEnv->GetMethodID(
3631af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        locationClass,
3641af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "setLongitude",
3651af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "(D)V"
3661af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        );
3671af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sCallbackEnv->CallVoidMethod(
3681af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        locationObject,
3691af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        setLongitude,
3701af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        location->longitude
3711af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        );
3721af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
3731af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jmethodID setTime = sCallbackEnv->GetMethodID(
3741af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        locationClass,
3751af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "setTime",
3761af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "(J)V"
3771af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        );
3781af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sCallbackEnv->CallVoidMethod(locationObject, setTime, location->timestamp);
3791af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
3801af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
3811af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if (flags & FLP_LOCATION_HAS_ALTITUDE) {
3821af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jmethodID setAltitude = sCallbackEnv->GetMethodID(
3831af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        locationClass,
3841af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "setAltitude",
3851af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "(D)V"
3861af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        );
3871af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sCallbackEnv->CallVoidMethod(locationObject, setAltitude, location->altitude);
3881af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
3891af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
3901af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if (flags & FLP_LOCATION_HAS_SPEED) {
3911af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jmethodID setSpeed = sCallbackEnv->GetMethodID(
3921af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        locationClass,
3931af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "setSpeed",
3941af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "(F)V"
3951af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        );
3961af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sCallbackEnv->CallVoidMethod(locationObject, setSpeed, location->speed);
3971af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
3981af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
3991af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if (flags & FLP_LOCATION_HAS_BEARING) {
4001af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jmethodID setBearing = sCallbackEnv->GetMethodID(
4011af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        locationClass,
4021af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "setBearing",
4031af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "(F)V"
4041af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        );
4051af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sCallbackEnv->CallVoidMethod(locationObject, setBearing, location->bearing);
4061af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
4071af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
4081af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if (flags & FLP_LOCATION_HAS_ACCURACY) {
4091af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jmethodID setAccuracy = sCallbackEnv->GetMethodID(
4101af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        locationClass,
4111af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "setAccuracy",
4121af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "(F)V"
4131af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        );
4141af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sCallbackEnv->CallVoidMethod(locationObject, setAccuracy, location->accuracy);
4151af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
4161af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
4171af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  // TODO: wire FlpLocation::sources_used when needed
418b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa
419b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa  sCallbackEnv->DeleteLocalRef(locationClass);
4201af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
4211af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
4221af4b0280af406cfc7eb46810f6b76e57b983e11destradaa/*
4231af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Helper function to serialize FlpLocation structures.
4241af4b0280af406cfc7eb46810f6b76e57b983e11destradaa */
4251af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void TranslateToObjectArray(
4261af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    int32_t locationsCount,
4271af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    FlpLocation** locations,
4281af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jobjectArray& locationsArray) {
4291af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jclass locationClass = sCallbackEnv->FindClass(LOCATION_CLASS_NAME);
4301af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  locationsArray = sCallbackEnv->NewObjectArray(
4311af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      locationsCount,
4321af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      locationClass,
4331af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      /* initialElement */ NULL
4341af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
4351af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
4361af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  for (int i = 0; i < locationsCount; ++i) {
4371af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jobject locationObject = NULL;
4381af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    TranslateToObject(locations[i], locationObject);
4391af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sCallbackEnv->SetObjectArrayElement(locationsArray, i, locationObject);
4401af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sCallbackEnv->DeleteLocalRef(locationObject);
4411af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
442b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa
443b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa  sCallbackEnv->DeleteLocalRef(locationClass);
4441af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
4451af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
4461af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void LocationCallback(int32_t locationsCount, FlpLocation** locations) {
4471af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(!IsValidCallbackThread()) {
4481af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
4491af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
4501af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
4511af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(locationsCount == 0 || locations == NULL) {
4521af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ALOGE(
4531af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        "Invalid LocationCallback. Count: %d, Locations: %p",
4541af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        locationsCount,
4551af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        locations
4561af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        );
4571af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
4581af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
4591af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
4601af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jobjectArray locationsArray = NULL;
4611af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  TranslateToObjectArray(locationsCount, locations, locationsArray);
4621af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
4631af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sCallbackEnv->CallVoidMethod(
4641af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sCallbacksObj,
4651af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sOnLocationReport,
4661af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      locationsArray
4671af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
4681af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  CheckExceptions(sCallbackEnv, __FUNCTION__);
469b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa
470b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa  if(locationsArray != NULL) {
471b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa    sCallbackEnv->DeleteLocalRef(locationsArray);
472b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa  }
4731af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
4741af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
4751af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void AcquireWakelock() {
4761af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
4771af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
4781af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
4791af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void ReleaseWakelock() {
4801af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  release_wake_lock(WAKE_LOCK_NAME);
4811af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
4821af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
4831af4b0280af406cfc7eb46810f6b76e57b983e11destradaaFlpCallbacks sFlpCallbacks = {
4841af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sizeof(FlpCallbacks),
4851af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  LocationCallback,
4861af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  AcquireWakelock,
4871af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  ReleaseWakelock,
4881af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  SetThreadEvent
4891af4b0280af406cfc7eb46810f6b76e57b983e11destradaa};
4901af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
4911af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void ReportData(char* data, int length) {
4921af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jstring stringData = NULL;
4931af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
4941af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(length != 0 && data != NULL) {
4951af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    stringData = sCallbackEnv->NewString(reinterpret_cast<jchar*>(data), length);
4961af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  } else {
4971af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ALOGE("Invalid ReportData callback. Length: %d, Data: %p", length, data);
4981af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
4991af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
5001af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5011af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sCallbackEnv->CallVoidMethod(sCallbacksObj, sOnDataReport, stringData);
5021af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  CheckExceptions(sCallbackEnv, __FUNCTION__);
5031af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
5041af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5051af4b0280af406cfc7eb46810f6b76e57b983e11destradaaFlpDiagnosticCallbacks sFlpDiagnosticCallbacks = {
5061af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sizeof(FlpDiagnosticCallbacks),
5071af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  SetThreadEvent,
5081af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  ReportData
5091af4b0280af406cfc7eb46810f6b76e57b983e11destradaa};
5101af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5111af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void GeofenceTransitionCallback(
5121af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    int32_t geofenceId,
5131af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    FlpLocation* location,
5141af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    int32_t transition,
5151af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    FlpUtcTime timestamp,
5161af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    uint32_t sourcesUsed
5171af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ) {
5181af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(!IsValidCallbackThread()) {
5191af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
5201af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
5211af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5221af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(location == NULL) {
5231af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ALOGE("GeofenceTransition received with invalid location: %p", location);
5241af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
5251af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
5261af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5271af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jobject locationObject = NULL;
5281af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  TranslateToObject(location, locationObject);
5291af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5301af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sCallbackEnv->CallVoidMethod(
5311af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sCallbacksObj,
5321af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sOnGeofenceTransition,
5331af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      geofenceId,
5341af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      locationObject,
5351af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      transition,
5361af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      timestamp,
5371af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sourcesUsed
5381af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
5391af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  CheckExceptions(sCallbackEnv, __FUNCTION__);
540b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa
541b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa  if(locationObject != NULL) {
542b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa    sCallbackEnv->DeleteLocalRef(locationObject);
543b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa  }
5441af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
5451af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5461af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void GeofenceMonitorStatusCallback(
5471af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    int32_t status,
5481af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    uint32_t source,
5491af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    FlpLocation* lastLocation) {
5501af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(!IsValidCallbackThread()) {
5511af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
5521af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
5531af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5541af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jobject locationObject = NULL;
5551af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(lastLocation != NULL) {
5561af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    TranslateToObject(lastLocation, locationObject);
5571af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
5581af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5591af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sCallbackEnv->CallVoidMethod(
5601af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sCallbacksObj,
5611af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sOnGeofenceMonitorStatus,
5621af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      status,
5631af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      source,
5641af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      locationObject
5651af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
5661af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  CheckExceptions(sCallbackEnv, __FUNCTION__);
567b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa
568b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa  if(locationObject != NULL) {
569b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa    sCallbackEnv->DeleteLocalRef(locationObject);
570b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa  }
5711af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
5721af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5731af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void GeofenceAddCallback(int32_t geofenceId, int32_t result) {
5741af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(!IsValidCallbackThread()) {
5751af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
5761af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
5771af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5781af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sCallbackEnv->CallVoidMethod(sCallbacksObj, sOnGeofenceAdd, geofenceId, result);
5791af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  CheckExceptions(sCallbackEnv, __FUNCTION__);
5801af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
5811af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5821af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void GeofenceRemoveCallback(int32_t geofenceId, int32_t result) {
5831af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(!IsValidCallbackThread()) {
5841af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
5851af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
5861af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5871af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sCallbackEnv->CallVoidMethod(
5881af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sCallbacksObj,
5891af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sOnGeofenceRemove,
5901af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      geofenceId,
5911af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      result
5921af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
5931af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  CheckExceptions(sCallbackEnv, __FUNCTION__);
5941af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
5951af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
5961af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void GeofencePauseCallback(int32_t geofenceId, int32_t result) {
5971af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(!IsValidCallbackThread()) {
5981af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
5991af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
6001af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6011af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sCallbackEnv->CallVoidMethod(
6021af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sCallbacksObj,
6031af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sOnGeofencePause,
6041af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      geofenceId,
6051af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      result
6061af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
6071af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  CheckExceptions(sCallbackEnv, __FUNCTION__);
6081af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
6091af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6101af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void GeofenceResumeCallback(int32_t geofenceId, int32_t result) {
6111af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(!IsValidCallbackThread()) {
6121af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
6131af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
6141af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6151af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sCallbackEnv->CallVoidMethod(
6161af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sCallbacksObj,
6171af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sOnGeofenceResume,
6181af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      geofenceId,
6191af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      result
6201af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
6211af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  CheckExceptions(sCallbackEnv, __FUNCTION__);
6221af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
6231af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6241af4b0280af406cfc7eb46810f6b76e57b983e11destradaaFlpGeofenceCallbacks sFlpGeofenceCallbacks = {
6251af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sizeof(FlpGeofenceCallbacks),
6261af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  GeofenceTransitionCallback,
6271af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  GeofenceMonitorStatusCallback,
6281af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  GeofenceAddCallback,
6291af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  GeofenceRemoveCallback,
6301af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  GeofencePauseCallback,
6311af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  GeofenceResumeCallback,
6321af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  SetThreadEvent
6331af4b0280af406cfc7eb46810f6b76e57b983e11destradaa};
6341af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6351af4b0280af406cfc7eb46810f6b76e57b983e11destradaa/*
6361af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Initializes the Fused Location Provider in the native side. It ensures that
6371af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * the Flp interfaces are initialized properly.
6381af4b0280af406cfc7eb46810f6b76e57b983e11destradaa */
6391af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void Init(JNIEnv* env, jobject obj) {
6401af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sHardwareDevice != NULL) {
6411af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ALOGD("Hardware Device already opened.");
6421af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
6431af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
6441af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6451af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  const hw_module_t* module = NULL;
6461af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, &module);
6471af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(err != 0) {
6481af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ALOGE("Error hw_get_module '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
6491af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
6501af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
6511af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6521af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  err = module->methods->open(
6530682809ad08db284d7110aab44108d5e9c310e6bdestradaa        module,
6541af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        FUSED_LOCATION_HARDWARE_MODULE_ID, &sHardwareDevice);
6551af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(err != 0) {
6561af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ALOGE("Error opening device '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
6571af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
6581af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
6591af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6601af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sFlpInterface = NULL;
6611af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  flp_device_t* flp_device = reinterpret_cast<flp_device_t*>(sHardwareDevice);
6621af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sFlpInterface = flp_device->get_flp_interface(flp_device);
6631af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6641af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpInterface != NULL) {
6651af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sFlpDiagnosticInterface = reinterpret_cast<const FlpDiagnosticInterface*>(
6661af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        sFlpInterface->get_extension(FLP_DIAGNOSTIC_INTERFACE)
6671af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        );
6681af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6691af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sFlpGeofencingInterface = reinterpret_cast<const FlpGeofencingInterface*>(
6701af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        sFlpInterface->get_extension(FLP_GEOFENCING_INTERFACE)
6711af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        );
6721af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6731af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sFlpDeviceContextInterface = reinterpret_cast<const FlpDeviceContextInterface*>(
6741af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        sFlpInterface->get_extension(FLP_DEVICE_CONTEXT_INTERFACE)
6751af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        );
6761af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
6771af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6781af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sCallbacksObj == NULL) {
6791af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sCallbacksObj = env->NewGlobalRef(obj);
6801af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
6811af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6821af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  // initialize the Flp interfaces
6831af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpInterface == NULL || sFlpInterface->init(&sFlpCallbacks) != 0) {
6841af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
6851af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
6861af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6871af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpDiagnosticInterface != NULL) {
6881af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sFlpDiagnosticInterface->init(&sFlpDiagnosticCallbacks);
6891af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
6901af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6911af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpGeofencingInterface != NULL) {
6921af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sFlpGeofencingInterface->init(&sFlpGeofenceCallbacks);
6931af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
6941af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6951af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  // TODO: inject any device context if when needed
6961af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
6971af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
6981af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jboolean IsSupported(JNIEnv* env, jclass clazz) {
6991af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  return sFlpInterface != NULL;
7001af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
7011af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7021af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jint GetBatchSize(JNIEnv* env, jobject object) {
7031af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpInterface == NULL) {
7041af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
7051af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
7061af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7071af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  return sFlpInterface->get_batch_size();
7081af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
7091af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7101af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void StartBatching(
7111af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    JNIEnv* env,
7121af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jobject object,
7131af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jint id,
7141af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jobject optionsObject) {
7151af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpInterface == NULL || optionsObject == NULL) {
7161af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
7171af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
7181af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7191af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  FlpBatchOptions options;
7201af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  TranslateFromObject(env, optionsObject, options);
7211af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  int result = sFlpInterface->start_batching(id, &options);
7221af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  ThrowOnError(env, result, __FUNCTION__);
7231af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
7241af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7251af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void UpdateBatchingOptions(
7261af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    JNIEnv* env,
7271af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jobject object,
7281af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jint id,
7291af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jobject optionsObject) {
7301af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpInterface == NULL || optionsObject == NULL) {
7311af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
7321af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
7331af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7341af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  FlpBatchOptions options;
7351af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  TranslateFromObject(env, optionsObject, options);
7361af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  int result = sFlpInterface->update_batching_options(id, &options);
7371af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  ThrowOnError(env, result, __FUNCTION__);
7381af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
7391af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7401af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void StopBatching(JNIEnv* env, jobject object, jint id) {
7411af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpInterface == NULL) {
7421af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
7431af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
7441af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7451af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sFlpInterface->stop_batching(id);
7461af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
7471af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7481af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void Cleanup(JNIEnv* env, jobject object) {
7491af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpInterface == NULL) {
7501af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
7511af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
7521af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7531af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sFlpInterface->cleanup();
7541af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7551af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sCallbacksObj != NULL) {
7561af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    env->DeleteGlobalRef(sCallbacksObj);
7571af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sCallbacksObj = NULL;
7581af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
7591af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7601af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sFlpInterface = NULL;
7611af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sFlpDiagnosticInterface = NULL;
7621af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sFlpDeviceContextInterface = NULL;
7631af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sFlpGeofencingInterface = NULL;
7641af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7651af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sHardwareDevice != NULL) {
7661af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sHardwareDevice->close(sHardwareDevice);
7671af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    sHardwareDevice = NULL;
7681af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
7691af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
7701af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7711af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void GetBatchedLocation(JNIEnv* env, jobject object, jint lastNLocations) {
7721af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpInterface == NULL) {
7731af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
7741af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
7751af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7761af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sFlpInterface->get_batched_location(lastNLocations);
7771af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
7781af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7791af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void InjectLocation(JNIEnv* env, jobject object, jobject locationObject) {
7801af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(locationObject == NULL) {
7811af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ALOGE("Invalid location for injection: %p", locationObject);
7821af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
7831af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
7841af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7851af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpInterface == NULL) {
7861af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    // there is no listener, bail
7871af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    return;
7881af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
7891af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7901af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  FlpLocation location;
7911af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  TranslateFromObject(env, locationObject, location);
7921af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  int result = sFlpInterface->inject_location(&location);
793264705a3f6a3220eb293898cf190eaed55e26970destradaa  if (result != FLP_RESULT_SUCCESS) {
7941af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    // do not throw but log, this operation should be fire and forget
7951af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ALOGE("Error %d in '%s'", result, __FUNCTION__);
7961af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
7971af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
7981af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
7991af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jboolean IsDiagnosticSupported() {
8001af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  return sFlpDiagnosticInterface != NULL;
8011af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
8021af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8031af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void InjectDiagnosticData(JNIEnv* env, jobject object, jstring stringData) {
8041af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(stringData == NULL) {
8051af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ALOGE("Invalid diagnostic data for injection: %p", stringData);
8061af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
8071af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
8081af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8091af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpDiagnosticInterface == NULL) {
8101af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
8111af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
8121af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8131af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  int length = env->GetStringLength(stringData);
8141af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  const jchar* data = env->GetStringChars(stringData, /* isCopy */ NULL);
8151af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(data == NULL) {
8161af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
8171af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
8181af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8191af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  int result = sFlpDiagnosticInterface->inject_data((char*) data, length);
8201af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  ThrowOnError(env, result, __FUNCTION__);
8211af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
8221af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8231af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jboolean IsDeviceContextSupported() {
8241af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  return sFlpDeviceContextInterface != NULL;
8251af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
8261af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8271af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void InjectDeviceContext(JNIEnv* env, jobject object, jint enabledMask) {
8281af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpDeviceContextInterface == NULL) {
8291af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
8301af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
8311af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8321af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  int result = sFlpDeviceContextInterface->inject_device_context(enabledMask);
8331af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  ThrowOnError(env, result, __FUNCTION__);
8341af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
8351af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8361af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic jboolean IsGeofencingSupported() {
8371af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  return sFlpGeofencingInterface != NULL;
8381af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
8391af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8401af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void AddGeofences(
8411af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    JNIEnv* env,
8421af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jobject object,
8430682809ad08db284d7110aab44108d5e9c310e6bdestradaa    jobjectArray geofenceRequestsArray) {
8440682809ad08db284d7110aab44108d5e9c310e6bdestradaa  if(geofenceRequestsArray == NULL) {
8450682809ad08db284d7110aab44108d5e9c310e6bdestradaa    ALOGE("Invalid Geofences to add: %p", geofenceRequestsArray);
8461af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
8471af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
8481af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8491af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if (sFlpGeofencingInterface == NULL) {
8501af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
8511af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
8521af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8530682809ad08db284d7110aab44108d5e9c310e6bdestradaa  jint geofenceRequestsCount = env->GetArrayLength(geofenceRequestsArray);
8540682809ad08db284d7110aab44108d5e9c310e6bdestradaa  if(geofenceRequestsCount == 0) {
8550682809ad08db284d7110aab44108d5e9c310e6bdestradaa    return;
8560682809ad08db284d7110aab44108d5e9c310e6bdestradaa  }
8570682809ad08db284d7110aab44108d5e9c310e6bdestradaa
8580682809ad08db284d7110aab44108d5e9c310e6bdestradaa  Geofence* geofences = new Geofence[geofenceRequestsCount];
8591af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if (geofences == NULL) {
8601af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_INSUFFICIENT_MEMORY, __FUNCTION__);
8611af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
8621af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8630682809ad08db284d7110aab44108d5e9c310e6bdestradaa  for (int i = 0; i < geofenceRequestsCount; ++i) {
8640682809ad08db284d7110aab44108d5e9c310e6bdestradaa    geofences[i].data = new GeofenceData();
8650682809ad08db284d7110aab44108d5e9c310e6bdestradaa    geofences[i].options = new GeofenceOptions();
8660682809ad08db284d7110aab44108d5e9c310e6bdestradaa    jobject geofenceObject = env->GetObjectArrayElement(geofenceRequestsArray, i);
8671af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8680682809ad08db284d7110aab44108d5e9c310e6bdestradaa    TranslateGeofenceFromGeofenceHardwareRequestParcelable(env, geofenceObject, geofences[i]);
869b75cb3aeb429ea6b6b0d34c41ad292b2a124fcf2destradaa    env->DeleteLocalRef(geofenceObject);
8701af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
8711af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8720682809ad08db284d7110aab44108d5e9c310e6bdestradaa  sFlpGeofencingInterface->add_geofences(geofenceRequestsCount, &geofences);
8730682809ad08db284d7110aab44108d5e9c310e6bdestradaa  if (geofences != NULL) {
8740682809ad08db284d7110aab44108d5e9c310e6bdestradaa    for(int i = 0; i < geofenceRequestsCount; ++i) {
8750682809ad08db284d7110aab44108d5e9c310e6bdestradaa      delete geofences[i].data;
8760682809ad08db284d7110aab44108d5e9c310e6bdestradaa      delete geofences[i].options;
8770682809ad08db284d7110aab44108d5e9c310e6bdestradaa    }
8780682809ad08db284d7110aab44108d5e9c310e6bdestradaa    delete[] geofences;
8790682809ad08db284d7110aab44108d5e9c310e6bdestradaa  }
8801af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
8811af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8821af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void PauseGeofence(JNIEnv* env, jobject object, jint geofenceId) {
8831af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpGeofencingInterface == NULL) {
8841af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
8851af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
8861af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8871af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sFlpGeofencingInterface->pause_geofence(geofenceId);
8881af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
8891af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8901af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void ResumeGeofence(
8911af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    JNIEnv* env,
8921af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jobject object,
8931af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jint geofenceId,
8941af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jint monitorTransitions) {
8951af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpGeofencingInterface == NULL) {
8961af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
8971af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
8981af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
8991af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sFlpGeofencingInterface->resume_geofence(geofenceId, monitorTransitions);
9001af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
9011af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
9021af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void ModifyGeofenceOption(
9031af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    JNIEnv* env,
9041af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jobject object,
9051af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jint geofenceId,
9061af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jint lastTransition,
9071af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jint monitorTransitions,
9081af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jint notificationResponsiveness,
9091af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jint unknownTimer,
9101af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jint sourcesToUse) {
9111af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpGeofencingInterface == NULL) {
9121af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
9131af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
9141af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
9151af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  GeofenceOptions options = {
9161af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      lastTransition,
9171af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      monitorTransitions,
9181af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      notificationResponsiveness,
9191af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      unknownTimer,
9201af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      (uint32_t)sourcesToUse
9211af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  };
9221af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
9231af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sFlpGeofencingInterface->modify_geofence_option(geofenceId, &options);
9241af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
9251af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
9261af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic void RemoveGeofences(
9271af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    JNIEnv* env,
9281af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jobject object,
9291af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    jintArray geofenceIdsArray) {
9301af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(sFlpGeofencingInterface == NULL) {
9311af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
9321af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
9331af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
9341af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jsize geofenceIdsCount = env->GetArrayLength(geofenceIdsArray);
9351af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  jint* geofenceIds = env->GetIntArrayElements(geofenceIdsArray, /* isCopy */ NULL);
9361af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  if(geofenceIds == NULL) {
9371af4b0280af406cfc7eb46810f6b76e57b983e11destradaa    ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
9381af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  }
9391af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
9401af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  sFlpGeofencingInterface->remove_geofences(geofenceIdsCount, geofenceIds);
9417f02eb2c84c0a39e6357aca10a4fda1dd090a8a6destradaa  env->ReleaseIntArrayElements(geofenceIdsArray, geofenceIds, 0 /*mode*/);
9421af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
9431af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
9441af4b0280af406cfc7eb46810f6b76e57b983e11destradaastatic JNINativeMethod sMethods[] = {
9451af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  //{"name", "signature", functionPointer }
9461af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  {"nativeClassInit", "()V", reinterpret_cast<void*>(ClassInit)},
9471af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  {"nativeInit", "()V", reinterpret_cast<void*>(Init)},
9481af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  {"nativeCleanup", "()V", reinterpret_cast<void*>(Cleanup)},
9491af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  {"nativeIsSupported", "()Z", reinterpret_cast<void*>(IsSupported)},
9501af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  {"nativeGetBatchSize", "()I", reinterpret_cast<void*>(GetBatchSize)},
9510682809ad08db284d7110aab44108d5e9c310e6bdestradaa  {"nativeStartBatching",
9520682809ad08db284d7110aab44108d5e9c310e6bdestradaa        "(ILandroid/location/FusedBatchOptions;)V",
9531af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        reinterpret_cast<void*>(StartBatching)},
9540682809ad08db284d7110aab44108d5e9c310e6bdestradaa  {"nativeUpdateBatchingOptions",
9550682809ad08db284d7110aab44108d5e9c310e6bdestradaa        "(ILandroid/location/FusedBatchOptions;)V",
9561af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        reinterpret_cast<void*>(UpdateBatchingOptions)},
9571af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  {"nativeStopBatching", "(I)V", reinterpret_cast<void*>(StopBatching)},
9580682809ad08db284d7110aab44108d5e9c310e6bdestradaa  {"nativeRequestBatchedLocation",
9590682809ad08db284d7110aab44108d5e9c310e6bdestradaa        "(I)V",
9601af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        reinterpret_cast<void*>(GetBatchedLocation)},
9610682809ad08db284d7110aab44108d5e9c310e6bdestradaa  {"nativeInjectLocation",
9620682809ad08db284d7110aab44108d5e9c310e6bdestradaa        "(Landroid/location/Location;)V",
9631af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        reinterpret_cast<void*>(InjectLocation)},
9640682809ad08db284d7110aab44108d5e9c310e6bdestradaa  {"nativeIsDiagnosticSupported",
9650682809ad08db284d7110aab44108d5e9c310e6bdestradaa        "()Z",
9661af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        reinterpret_cast<void*>(IsDiagnosticSupported)},
9670682809ad08db284d7110aab44108d5e9c310e6bdestradaa  {"nativeInjectDiagnosticData",
9680682809ad08db284d7110aab44108d5e9c310e6bdestradaa        "(Ljava/lang/String;)V",
9691af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        reinterpret_cast<void*>(InjectDiagnosticData)},
9700682809ad08db284d7110aab44108d5e9c310e6bdestradaa  {"nativeIsDeviceContextSupported",
9710682809ad08db284d7110aab44108d5e9c310e6bdestradaa        "()Z",
9721af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        reinterpret_cast<void*>(IsDeviceContextSupported)},
9730682809ad08db284d7110aab44108d5e9c310e6bdestradaa  {"nativeInjectDeviceContext",
9740682809ad08db284d7110aab44108d5e9c310e6bdestradaa        "(I)V",
9751af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        reinterpret_cast<void*>(InjectDeviceContext)},
9760682809ad08db284d7110aab44108d5e9c310e6bdestradaa  {"nativeIsGeofencingSupported",
9770682809ad08db284d7110aab44108d5e9c310e6bdestradaa        "()Z",
9781af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        reinterpret_cast<void*>(IsGeofencingSupported)},
9790682809ad08db284d7110aab44108d5e9c310e6bdestradaa  {"nativeAddGeofences",
9800682809ad08db284d7110aab44108d5e9c310e6bdestradaa        "([Landroid/hardware/location/GeofenceHardwareRequestParcelable;)V",
9811af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        reinterpret_cast<void*>(AddGeofences)},
9821af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  {"nativePauseGeofence", "(I)V", reinterpret_cast<void*>(PauseGeofence)},
9831af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  {"nativeResumeGeofence", "(II)V", reinterpret_cast<void*>(ResumeGeofence)},
9840682809ad08db284d7110aab44108d5e9c310e6bdestradaa  {"nativeModifyGeofenceOption",
9850682809ad08db284d7110aab44108d5e9c310e6bdestradaa        "(IIIIII)V",
9861af4b0280af406cfc7eb46810f6b76e57b983e11destradaa        reinterpret_cast<void*>(ModifyGeofenceOption)},
9871af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  {"nativeRemoveGeofences", "([I)V", reinterpret_cast<void*>(RemoveGeofences)}
9881af4b0280af406cfc7eb46810f6b76e57b983e11destradaa};
9891af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
9901af4b0280af406cfc7eb46810f6b76e57b983e11destradaa/*
9911af4b0280af406cfc7eb46810f6b76e57b983e11destradaa * Registration method invoked on JNI Load.
9921af4b0280af406cfc7eb46810f6b76e57b983e11destradaa */
9931af4b0280af406cfc7eb46810f6b76e57b983e11destradaaint register_android_server_location_FlpHardwareProvider(JNIEnv* env) {
9941af4b0280af406cfc7eb46810f6b76e57b983e11destradaa  return jniRegisterNativeMethods(
9951af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      env,
9961af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      "com/android/server/location/FlpHardwareProvider",
9971af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      sMethods,
9981af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      NELEM(sMethods)
9991af4b0280af406cfc7eb46810f6b76e57b983e11destradaa      );
10001af4b0280af406cfc7eb46810f6b76e57b983e11destradaa}
10011af4b0280af406cfc7eb46810f6b76e57b983e11destradaa
10021af4b0280af406cfc7eb46810f6b76e57b983e11destradaa} /* name-space Android */
1003