Merge "Common code for 4 jni Location conversions"
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 8bc72de..fdaba0b 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -263,8 +263,6 @@
 
     private Object mLock = new Object();
 
-    private int mLocationFlags = LOCATION_INVALID;
-
     // current status
     private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
 
@@ -1451,7 +1449,6 @@
             native_stop();
             mTimeToFirstFix = 0;
             mLastFixTime = 0;
-            mLocationFlags = LOCATION_INVALID;
 
             // reset SV count to zero
             updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
@@ -1475,12 +1472,9 @@
     /**
      * called from native code to update our position.
      */
-    private void reportLocation(int flags, double latitude, double longitude, double altitude,
-            float speedMetersPerSecond, float bearing, float horizontalAccuracyMeters,
-            float verticalAccuracyMeters, float speedAccuracyMetersPerSeconds,
-            float bearingAccuracyDegrees, long timestamp) {
-        if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
-            mItarSpeedLimitExceeded = speedMetersPerSecond > ITAR_SPEED_LIMIT_METERS_PER_SECOND;
+    private void reportLocation(boolean hasLatLong, Location location) {
+        if (location.hasSpeed()) {
+            mItarSpeedLimitExceeded = location.getSpeed() > ITAR_SPEED_LIMIT_METERS_PER_SECOND;
         }
 
         if (mItarSpeedLimitExceeded) {
@@ -1489,54 +1483,13 @@
             return;  // No output of location allowed
         }
 
-        if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
-                " timestamp: " + timestamp + " flags: " + flags);
+        if (VERBOSE) Log.v(TAG, "reportLocation " + location.toString());
 
         synchronized (mLocation) {
-            mLocationFlags = flags;
-            if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
-                mLocation.setLatitude(latitude);
-                mLocation.setLongitude(longitude);
-                mLocation.setTime(timestamp);
-                // It would be nice to push the elapsed real-time timestamp
-                // further down the stack, but this is still useful
-                mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
-            }
-            if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
-                mLocation.setAltitude(altitude);
-            } else {
-                mLocation.removeAltitude();
-            }
-            if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
-                mLocation.setSpeed(speedMetersPerSecond);
-            } else {
-                mLocation.removeSpeed();
-            }
-            if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
-                mLocation.setBearing(bearing);
-            } else {
-                mLocation.removeBearing();
-            }
-            if ((flags & LOCATION_HAS_HORIZONTAL_ACCURACY) == LOCATION_HAS_HORIZONTAL_ACCURACY) {
-                mLocation.setAccuracy(horizontalAccuracyMeters);
-            } else {
-                mLocation.removeAccuracy();
-            }
-            if ((flags & LOCATION_HAS_VERTICAL_ACCURACY) == LOCATION_HAS_VERTICAL_ACCURACY) {
-              mLocation.setVerticalAccuracyMeters(verticalAccuracyMeters);
-            } else {
-              mLocation.removeVerticalAccuracy();
-            }
-            if((flags & LOCATION_HAS_SPEED_ACCURACY) == LOCATION_HAS_SPEED_ACCURACY) {
-              mLocation.setSpeedAccuracyMetersPerSecond(speedAccuracyMetersPerSeconds);
-            } else {
-              mLocation.removeSpeedAccuracy();
-            }
-            if((flags & LOCATION_HAS_BEARING_ACCURACY) == LOCATION_HAS_BEARING_ACCURACY) {
-              mLocation.setBearingAccuracyDegrees(bearingAccuracyDegrees);
-            } else {
-              mLocation.removeBearingAccuracy();
-            }
+            mLocation = location;
+            // It would be nice to push the elapsed real-time timestamp
+            // further down the stack, but this is still useful
+            mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
             mLocation.setExtras(mLocationExtras);
 
             try {
@@ -1548,7 +1501,7 @@
 
         mLastFixTime = System.currentTimeMillis();
         // report time to first fix
-        if (mTimeToFirstFix == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
+        if (mTimeToFirstFix == 0 && hasLatLong) {
             mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);
             if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);
 
@@ -1871,52 +1824,6 @@
     }
 
     /**
-     * Helper method to construct a location object.
-     */
-    private Location buildLocation(
-            int flags,
-            double latitude,
-            double longitude,
-            double altitude,
-            float speed,
-            float bearing,
-            float horizontalAccuracy,
-            float verticalAccuracy,
-            float speedAccuracy,
-            float bearingAccuracy,
-            long timestamp) {
-        Location location = new Location(LocationManager.GPS_PROVIDER);
-        if((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
-            location.setLatitude(latitude);
-            location.setLongitude(longitude);
-            location.setTime(timestamp);
-            location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
-        }
-        if((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
-            location.setAltitude(altitude);
-        }
-        if((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
-            location.setSpeed(speed);
-        }
-        if((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
-            location.setBearing(bearing);
-        }
-        if((flags & LOCATION_HAS_HORIZONTAL_ACCURACY) == LOCATION_HAS_HORIZONTAL_ACCURACY) {
-            location.setAccuracy(horizontalAccuracy);
-        }
-        if((flags & LOCATION_HAS_VERTICAL_ACCURACY) == LOCATION_HAS_VERTICAL_ACCURACY) {
-          location.setVerticalAccuracyMeters(verticalAccuracy);
-        }
-        if((flags & LOCATION_HAS_SPEED_ACCURACY) == LOCATION_HAS_SPEED_ACCURACY) {
-          location.setSpeedAccuracyMetersPerSecond(speedAccuracy);
-        }
-        if((flags & LOCATION_HAS_BEARING_ACCURACY) == LOCATION_HAS_BEARING_ACCURACY) {
-          location.setBearingAccuracyDegrees(bearingAccuracy);
-        }
-        return location;
-    }
-
-    /**
      * Converts the GPS HAL status to the internal Geofence Hardware status.
      */
     private int getGeofenceStatus(int status) {
@@ -1942,25 +1849,12 @@
      * Called from native to report GPS Geofence transition
      * All geofence callbacks are called on the same thread
      */
-    private void reportGeofenceTransition(int geofenceId, int flags, double latitude,
-            double longitude, double altitude, float speed, float bearing, float horizontalAccuracy,
-            float verticalAccuracy, float speedAccuracy, float bearingAccuracy, long timestamp,
-            int transition, long transitionTimestamp) {
+    private void reportGeofenceTransition(int geofenceId, Location location, int transition,
+                                          long transitionTimestamp) {
         if (mGeofenceHardwareImpl == null) {
             mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
         }
-        Location location = buildLocation(
-                flags,
-                latitude,
-                longitude,
-                altitude,
-                speed,
-                bearing,
-                horizontalAccuracy,
-                verticalAccuracy,
-                speedAccuracy,
-                bearingAccuracy,
-                timestamp);
+
         mGeofenceHardwareImpl.reportGeofenceTransition(
                 geofenceId,
                 location,
@@ -1973,24 +1867,10 @@
     /**
      * called from native code to report GPS status change.
      */
-    private void reportGeofenceStatus(int status, int flags, double latitude,
-            double longitude, double altitude, float speed, float bearing, float horizontalAccuracy,
-            float verticalAccuracy, float speedAccuracy, float bearingAccuracy, long timestamp) {
+    private void reportGeofenceStatus(int status, Location location) {
         if (mGeofenceHardwareImpl == null) {
             mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
         }
-        Location location = buildLocation(
-                flags,
-                latitude,
-                longitude,
-                altitude,
-                speed,
-                bearing,
-                horizontalAccuracy,
-                verticalAccuracy,
-                speedAccuracy,
-                bearingAccuracy,
-                timestamp);
         int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
         if(status == GPS_GEOFENCE_AVAILABLE) {
             monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 1578562..4c89705 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -289,6 +289,40 @@
     return env;
 }
 
+static jobject translateLocation(JNIEnv* env, const hardware::gnss::V1_0::GnssLocation& location) {
+    JavaObject object(env, "android/location/Location", "gps");
+
+    uint16_t flags = static_cast<uint32_t>(location.gnssLocationFlags);
+    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_LAT_LONG) {
+        SET(Latitude, location.latitudeDegrees);
+        SET(Longitude, location.longitudeDegrees);
+    }
+    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_ALTITUDE) {
+        SET(Altitude, location.altitudeMeters);
+    }
+    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED) {
+        SET(Speed, location.speedMetersPerSec);
+    }
+    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING) {
+        SET(Bearing, location.bearingDegrees);
+    }
+    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
+        SET(Accuracy, location.horizontalAccuracyMeters);
+    }
+    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
+        SET(VerticalAccuracyMeters, location.verticalAccuracyMeters);
+    }
+    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED_ACCURACY) {
+        SET(SpeedAccuracyMetersPerSecond, location.speedAccuracyMetersPerSecond);
+    }
+    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING_ACCURACY) {
+        SET(BearingAccuracyDegrees, location.bearingAccuracyDegrees);
+    }
+    SET(Time, location.timestamp);
+
+    return object.get();
+}
+
 /*
  * GnssCallback class implements the callback methods for IGnss interface.
  */
@@ -321,19 +355,15 @@
 Return<void> GnssCallback::gnssLocationCb(
         const ::android::hardware::gnss::V1_0::GnssLocation& location) {
     JNIEnv* env = getJniEnv();
+
+    jobject jLocation = translateLocation(env, location);
+    bool hasLatLong = (static_cast<uint32_t>(location.gnssLocationFlags) &
+            hardware::gnss::V1_0::GnssLocationFlags::HAS_LAT_LONG) != 0;
+
     env->CallVoidMethod(mCallbacksObj,
                         method_reportLocation,
-                        location.gnssLocationFlags,
-                        static_cast<jdouble>(location.latitudeDegrees),
-                        static_cast<jdouble>(location.longitudeDegrees),
-                        static_cast<jdouble>(location.altitudeMeters),
-                        static_cast<jfloat>(location.speedMetersPerSec),
-                        static_cast<jfloat>(location.bearingDegrees),
-                        static_cast<jfloat>(location.horizontalAccuracyMeters),
-                        static_cast<jfloat>(location.verticalAccuracyMeters),
-                        static_cast<jfloat>(location.speedAccuracyMetersPerSecond),
-                        static_cast<jfloat>(location.bearingAccuracyDegrees),
-                        static_cast<jlong>(location.timestamp));
+                        boolToJbool(hasLatLong),
+                        jLocation);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     return Void();
 }
@@ -463,20 +493,12 @@
         hardware::gnss::V1_0::GnssUtcTime timestamp) {
     JNIEnv* env = getJniEnv();
 
+    jobject jLocation = translateLocation(env, location);
+
     env->CallVoidMethod(mCallbacksObj,
                         method_reportGeofenceTransition,
                         geofenceId,
-                        location.gnssLocationFlags,
-                        static_cast<jdouble>(location.latitudeDegrees),
-                        static_cast<jdouble>(location.longitudeDegrees),
-                        static_cast<jdouble>(location.altitudeMeters),
-                        static_cast<jfloat>(location.speedMetersPerSec),
-                        static_cast<jfloat>(location.bearingDegrees),
-                        static_cast<jfloat>(location.horizontalAccuracyMeters),
-                        static_cast<jfloat>(location.verticalAccuracyMeters),
-                        static_cast<jfloat>(location.speedAccuracyMetersPerSecond),
-                        static_cast<jfloat>(location.bearingAccuracyDegrees),
-                        static_cast<jlong>(location.timestamp),
+                        jLocation,
                         transition,
                         timestamp);
 
@@ -488,20 +510,13 @@
         GeofenceAvailability status,
         const android::hardware::gnss::V1_0::GnssLocation& location) {
     JNIEnv* env = getJniEnv();
+
+    jobject jLocation = translateLocation(env, location);
+
     env->CallVoidMethod(mCallbacksObj,
                         method_reportGeofenceStatus,
                         status,
-                        location.gnssLocationFlags,
-                        static_cast<jdouble>(location.latitudeDegrees),
-                        static_cast<jdouble>(location.longitudeDegrees),
-                        static_cast<jdouble>(location.altitudeMeters),
-                        static_cast<jfloat>(location.speedMetersPerSec),
-                        static_cast<jfloat>(location.bearingDegrees),
-                        static_cast<jfloat>(location.horizontalAccuracyMeters),
-                        static_cast<jfloat>(location.verticalAccuracyMeters),
-                        static_cast<jfloat>(location.speedAccuracyMetersPerSecond),
-                        static_cast<jfloat>(location.bearingAccuracyDegrees),
-                        static_cast<jlong>(location.timestamp));
+                        jLocation);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     return Void();
 }
@@ -949,9 +964,6 @@
     Return<void> gnssLocationBatchCb(
         const ::android::hardware::hidl_vec<hardware::gnss::V1_0::GnssLocation> & locations)
         override;
- private:
-    jobject translateLocation(
-            JNIEnv* env, const hardware::gnss::V1_0::GnssLocation* location);
 };
 
 Return<void> GnssBatchingCallback::gnssLocationBatchCb(
@@ -962,7 +974,7 @@
             env->FindClass("android/location/Location"), nullptr);
 
     for (uint16_t i = 0; i < locations.size(); ++i) {
-        jobject jLocation = translateLocation(env, &locations[i]);
+        jobject jLocation = translateLocation(env, locations[i]);
         env->SetObjectArrayElement(jLocations, i, jLocation);
         env->DeleteLocalRef(jLocation);
     }
@@ -975,45 +987,9 @@
     return Void();
 }
 
-// TODO: Use this common code to translate location for Geofencing and regular Location
-jobject GnssBatchingCallback::translateLocation(
-        JNIEnv* env, const hardware::gnss::V1_0::GnssLocation* location) {
-    JavaObject object(env, "android/location/Location", "gps");
-
-    uint16_t flags = static_cast<uint32_t>(location->gnssLocationFlags);
-    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_LAT_LONG) {
-        SET(Latitude, location->latitudeDegrees);
-        SET(Longitude, location->longitudeDegrees);
-    }
-    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_ALTITUDE) {
-        SET(Altitude, location->altitudeMeters);
-    }
-    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED) {
-        SET(Speed, location->speedMetersPerSec);
-    }
-    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING) {
-        SET(Bearing, location->bearingDegrees);
-    }
-    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
-        SET(Accuracy, location->horizontalAccuracyMeters);
-    }
-    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
-        SET(VerticalAccuracyMeters, location->verticalAccuracyMeters);
-    }
-    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED_ACCURACY) {
-        SET(SpeedAccuracyMetersPerSecond, location->speedAccuracyMetersPerSecond);
-    }
-    if (flags & hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING_ACCURACY) {
-        SET(BearingAccuracyDegrees, location->bearingAccuracyDegrees);
-    }
-    SET(Time, location->timestamp);
-
-    return object.get();
-}
-
-
 static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
-    method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFFFFJ)V");
+    method_reportLocation = env->GetMethodID(clazz, "reportLocation",
+            "(ZLandroid/location/Location;)V");
     method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
     method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
     method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
@@ -1027,9 +1003,9 @@
     method_requestSetID = env->GetMethodID(clazz, "requestSetID", "(I)V");
     method_requestUtcTime = env->GetMethodID(clazz, "requestUtcTime", "()V");
     method_reportGeofenceTransition = env->GetMethodID(clazz, "reportGeofenceTransition",
-            "(IIDDDFFFFFFJIJ)V");
+            "(ILandroid/location/Location;IJ)V");
     method_reportGeofenceStatus = env->GetMethodID(clazz, "reportGeofenceStatus",
-            "(IIDDDFFFFFFJ)V");
+            "(ILandroid/location/Location;)V");
     method_reportGeofenceAddStatus = env->GetMethodID(clazz, "reportGeofenceAddStatus",
             "(II)V");
     method_reportGeofenceRemoveStatus = env->GetMethodID(clazz, "reportGeofenceRemoveStatus",