Update location framework to accept raw data from GPS HAL.
Change-Id: Ib4feca004b53fa89dcece4299974ab08913455a0
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 10382ba..67e58a6 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -16,6 +16,27 @@
package com.android.server;
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ProviderRequest;
+import com.android.internal.os.BackgroundThread;
+import com.android.server.location.FlpHardwareProvider;
+import com.android.server.location.FusedProxy;
+import com.android.server.location.GeocoderProxy;
+import com.android.server.location.GeofenceManager;
+import com.android.server.location.GeofenceProxy;
+import com.android.server.location.GpsLocationProvider;
+import com.android.server.location.GpsMeasurementsProvider;
+import com.android.server.location.LocationBlacklist;
+import com.android.server.location.LocationFudger;
+import com.android.server.location.LocationProviderInterface;
+import com.android.server.location.LocationProviderProxy;
+import com.android.server.location.LocationRequestStatistics;
+import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
+import com.android.server.location.LocationRequestStatistics.PackageStatistics;
+import com.android.server.location.MockProvider;
+import com.android.server.location.PassiveProvider;
+
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -36,6 +57,7 @@
import android.location.Criteria;
import android.location.GeocoderParams;
import android.location.Geofence;
+import android.location.IGpsMeasurementsListener;
import android.location.IGpsStatusListener;
import android.location.IGpsStatusProvider;
import android.location.ILocationListener;
@@ -62,26 +84,6 @@
import android.util.Log;
import android.util.Slog;
-import com.android.internal.content.PackageMonitor;
-import com.android.internal.location.ProviderProperties;
-import com.android.internal.location.ProviderRequest;
-import com.android.internal.os.BackgroundThread;
-import com.android.server.location.FlpHardwareProvider;
-import com.android.server.location.FusedProxy;
-import com.android.server.location.GeocoderProxy;
-import com.android.server.location.GeofenceProxy;
-import com.android.server.location.GeofenceManager;
-import com.android.server.location.GpsLocationProvider;
-import com.android.server.location.LocationBlacklist;
-import com.android.server.location.LocationFudger;
-import com.android.server.location.LocationProviderInterface;
-import com.android.server.location.LocationProviderProxy;
-import com.android.server.location.LocationRequestStatistics;
-import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
-import com.android.server.location.LocationRequestStatistics.PackageStatistics;
-import com.android.server.location.MockProvider;
-import com.android.server.location.PassiveProvider;
-
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -154,6 +156,7 @@
private LocationWorkerHandler mLocationHandler;
private PassiveProvider mPassiveProvider; // track passive provider for special cases
private LocationBlacklist mBlacklist;
+ private GpsMeasurementsProvider mGpsMeasurementsProvider;
// --- fields below are protected by mLock ---
// Set of providers that are explicitly enabled
@@ -403,6 +406,7 @@
addProviderLocked(gpsProvider);
mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider);
}
+ mGpsMeasurementsProvider = gpsProvider.getGpsMeasurementsProvider();
/*
Load package name(s) containing location provider support.
@@ -1804,6 +1808,36 @@
}
@Override
+ public boolean addGpsMeasurementsListener(
+ IGpsMeasurementsListener listener,
+ String packageName) {
+ int allowedResolutionLevel = getCallerAllowedResolutionLevel();
+ checkResolutionLevelIsSufficientForProviderUse(
+ allowedResolutionLevel,
+ LocationManager.GPS_PROVIDER);
+
+ int uid = Binder.getCallingUid();
+ long identity = Binder.clearCallingIdentity();
+ boolean hasLocationAccess;
+ try {
+ hasLocationAccess = checkLocationAccess(uid, packageName, allowedResolutionLevel);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ if (!hasLocationAccess) {
+ return false;
+ }
+
+ return mGpsMeasurementsProvider.addListener(listener);
+ }
+
+ @Override
+ public boolean removeGpsMeasurementsListener(IGpsMeasurementsListener listener) {
+ return mGpsMeasurementsProvider.removeListener(listener);
+ }
+
+ @Override
public boolean sendExtraCommand(String provider, String command, Bundle extras) {
if (provider == null) {
// throw NullPointerException to remain compatible with previous implementation
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index c5b6c7b..8222155 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -16,6 +16,15 @@
package com.android.server.location;
+import com.android.internal.app.IAppOpsService;
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.location.GpsNetInitiatedHandler;
+import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
+import com.android.internal.location.ProviderProperties;
+import com.android.internal.location.ProviderRequest;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
@@ -28,6 +37,7 @@
import android.hardware.location.GeofenceHardwareImpl;
import android.location.Criteria;
import android.location.FusedBatchOptions;
+import android.location.GpsMeasurementsEvent;
import android.location.IGpsGeofenceHardware;
import android.location.IGpsStatusListener;
import android.location.IGpsStatusProvider;
@@ -46,7 +56,6 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
-import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
@@ -64,27 +73,17 @@
import android.util.Log;
import android.util.NtpTrustedTime;
-import com.android.internal.app.IAppOpsService;
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.location.GpsNetInitiatedHandler;
-import com.android.internal.location.ProviderProperties;
-import com.android.internal.location.ProviderRequest;
-import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneConstants;
-
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
-import java.util.ArrayList;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.Date;
import java.util.Map.Entry;
import java.util.Properties;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
/**
* A GPS implementation of LocationProvider used by LocationManager.
@@ -314,7 +313,12 @@
private final ILocationManager mILocationManager;
private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
private Bundle mLocationExtras = new Bundle();
- private ArrayList<Listener> mListeners = new ArrayList<Listener>();
+ private GpsStatusListenerHelper mListenerHelper = new GpsStatusListenerHelper() {
+ @Override
+ protected boolean isSupported() {
+ return native_is_measurement_supported();
+ }
+ };
// Handler for processing events
private Handler mHandler;
@@ -348,49 +352,29 @@
private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
@Override
public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
- if (listener == null) {
- throw new NullPointerException("listener is null in addGpsStatusListener");
- }
-
- synchronized (mListeners) {
- IBinder binder = listener.asBinder();
- int size = mListeners.size();
- for (int i = 0; i < size; i++) {
- Listener test = mListeners.get(i);
- if (binder.equals(test.mListener.asBinder())) {
- // listener already added
- return;
- }
- }
-
- Listener l = new Listener(listener);
- binder.linkToDeath(l, 0);
- mListeners.add(l);
- }
+ mListenerHelper.addListener(listener);
}
@Override
public void removeGpsStatusListener(IGpsStatusListener listener) {
- if (listener == null) {
- throw new NullPointerException("listener is null in addGpsStatusListener");
- }
+ mListenerHelper.removeListener(listener);
+ }
+ };
- synchronized (mListeners) {
- IBinder binder = listener.asBinder();
- Listener l = null;
- int size = mListeners.size();
- for (int i = 0; i < size && l == null; i++) {
- Listener test = mListeners.get(i);
- if (binder.equals(test.mListener.asBinder())) {
- l = test;
- }
- }
+ private final GpsMeasurementsProvider mGpsMeasurementsProvider = new GpsMeasurementsProvider() {
+ @Override
+ public boolean isSupported() {
+ return native_is_measurement_supported();
+ }
- if (l != null) {
- mListeners.remove(l);
- binder.unlinkToDeath(l, 0);
- }
- }
+ @Override
+ protected void onFirstListenerAdded() {
+ native_start_measurement_collection();
+ }
+
+ @Override
+ protected void onLastListenerRemoved() {
+ native_stop_measurement_collection();
}
};
@@ -402,6 +386,10 @@
return mGpsGeofenceBinder;
}
+ public GpsMeasurementsProvider getGpsMeasurementsProvider() {
+ return mGpsMeasurementsProvider;
+ }
+
private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@@ -892,26 +880,6 @@
}
}
- private final class Listener implements IBinder.DeathRecipient {
- final IGpsStatusListener mListener;
-
- Listener(IGpsStatusListener listener) {
- mListener = listener;
- }
-
- @Override
- public void binderDied() {
- if (DEBUG) Log.d(TAG, "GPS status listener died");
-
- synchronized (mListeners) {
- mListeners.remove(this);
- }
- if (mListener != null) {
- mListener.asBinder().unlinkToDeath(this, 0);
- }
- }
- }
-
private void updateClientUids(WorkSource source) {
// Update work source.
WorkSource[] changes = mClientSource.setReturningDiffs(source);
@@ -1185,20 +1153,7 @@
if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);
// notify status listeners
- synchronized (mListeners) {
- int size = mListeners.size();
- for (int i = 0; i < size; i++) {
- Listener listener = mListeners.get(i);
- try {
- listener.mListener.onFirstFix(mTimeToFirstFix);
- } catch (RemoteException e) {
- Log.w(TAG, "RemoteException in stopNavigating");
- mListeners.remove(listener);
- // adjust for size of list changing
- size--;
- }
- }
- }
+ mListenerHelper.onFirstFix(mTimeToFirstFix);
}
if (mSingleShot) {
@@ -1232,49 +1187,31 @@
private void reportStatus(int status) {
if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
- synchronized (mListeners) {
- boolean wasNavigating = mNavigating;
+ boolean wasNavigating = mNavigating;
+ switch (status) {
+ case GPS_STATUS_SESSION_BEGIN:
+ mNavigating = true;
+ mEngineOn = true;
+ break;
+ case GPS_STATUS_SESSION_END:
+ mNavigating = false;
+ break;
+ case GPS_STATUS_ENGINE_ON:
+ mEngineOn = true;
+ break;
+ case GPS_STATUS_ENGINE_OFF:
+ mEngineOn = false;
+ mNavigating = false;
+ break;
+ }
- switch (status) {
- case GPS_STATUS_SESSION_BEGIN:
- mNavigating = true;
- mEngineOn = true;
- break;
- case GPS_STATUS_SESSION_END:
- mNavigating = false;
- break;
- case GPS_STATUS_ENGINE_ON:
- mEngineOn = true;
- break;
- case GPS_STATUS_ENGINE_OFF:
- mEngineOn = false;
- mNavigating = false;
- break;
- }
+ if (wasNavigating != mNavigating) {
+ mListenerHelper.onStatusChanged(mNavigating);
- if (wasNavigating != mNavigating) {
- int size = mListeners.size();
- for (int i = 0; i < size; i++) {
- Listener listener = mListeners.get(i);
- try {
- if (mNavigating) {
- listener.mListener.onGpsStarted();
- } else {
- listener.mListener.onGpsStopped();
- }
- } catch (RemoteException e) {
- Log.w(TAG, "RemoteException in reportStatus");
- mListeners.remove(listener);
- // adjust for size of list changing
- size--;
- }
- }
-
- // send an intent to notify that the GPS has been enabled or disabled.
- Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
- intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- }
+ // send an intent to notify that the GPS has been enabled or disabled
+ Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
+ intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
}
@@ -1282,25 +1219,16 @@
* called from native code to update SV info
*/
private void reportSvStatus() {
-
int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
-
- synchronized (mListeners) {
- int size = mListeners.size();
- for (int i = 0; i < size; i++) {
- Listener listener = mListeners.get(i);
- try {
- listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
- mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
- mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK]);
- } catch (RemoteException e) {
- Log.w(TAG, "RemoteException in reportSvInfo");
- mListeners.remove(listener);
- // adjust for size of list changing
- size--;
- }
- }
- }
+ mListenerHelper.onSvStatusChanged(
+ svCount,
+ mSvs,
+ mSnrs,
+ mSvElevations,
+ mSvAzimuths,
+ mSvMasks[EPHEMERIS_MASK],
+ mSvMasks[ALMANAC_MASK],
+ mSvMasks[USED_FOR_FIX_MASK]);
if (VERBOSE) {
Log.v(TAG, "SV count: " + svCount +
@@ -1398,26 +1326,16 @@
* called from native code to report NMEA data received
*/
private void reportNmea(long timestamp) {
- synchronized (mListeners) {
- int size = mListeners.size();
- if (size > 0) {
- // don't bother creating the String if we have no listeners
- int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
- String nmea = new String(mNmeaBuffer, 0, length);
+ int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
+ String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
+ mListenerHelper.onNmeaReceived(timestamp, nmea);
+ }
- for (int i = 0; i < size; i++) {
- Listener listener = mListeners.get(i);
- try {
- listener.mListener.onNmeaReceived(timestamp, nmea);
- } catch (RemoteException e) {
- Log.w(TAG, "RemoteException in reportNmea");
- mListeners.remove(listener);
- // adjust for size of list changing
- size--;
- }
- }
- }
- }
+ /**
+ * called from native code - Gps Data callback
+ */
+ private void reportMeasurementData(GpsMeasurementsEvent event) {
+ mGpsMeasurementsProvider.onMeasurementsAvailable(event);
}
/**
@@ -1845,7 +1763,7 @@
Log.e(TAG, "No APN found to select.");
}
} catch (Exception e) {
- Log.e(TAG, "Error encountered on selectiong the APN.", e);
+ Log.e(TAG, "Error encountered on selecting the APN.", e);
} finally {
if (cursor != null) {
cursor.close();
@@ -2008,4 +1926,9 @@
private static native boolean native_remove_geofence(int geofenceId);
private static native boolean native_resume_geofence(int geofenceId, int transitions);
private static native boolean native_pause_geofence(int geofenceId);
+
+ // Gps Hal measurements support.
+ private static native boolean native_is_measurement_supported();
+ private static native boolean native_start_measurement_collection();
+ private static native boolean native_stop_measurement_collection();
}
diff --git a/services/core/java/com/android/server/location/GpsMeasurementsProvider.java b/services/core/java/com/android/server/location/GpsMeasurementsProvider.java
new file mode 100644
index 0000000..001f638
--- /dev/null
+++ b/services/core/java/com/android/server/location/GpsMeasurementsProvider.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.location;
+
+import android.location.GpsMeasurementsEvent;
+import android.location.IGpsMeasurementsListener;
+import android.os.RemoteException;
+
+/**
+ * An base implementation for GPS measurements provider.
+ * It abstracts out the responsibility of handling listeners, while still allowing technology
+ * specific implementations to be built.
+ *
+ * @hide
+ */
+public abstract class GpsMeasurementsProvider
+ extends RemoteListenerHelper<IGpsMeasurementsListener> {
+
+ public void onMeasurementsAvailable(final GpsMeasurementsEvent event) {
+ ListenerOperation<IGpsMeasurementsListener> operation =
+ new ListenerOperation<IGpsMeasurementsListener>() {
+ @Override
+ public void execute(IGpsMeasurementsListener listener) throws RemoteException {
+ listener.onGpsMeasurementsReceived(event);
+ }
+ };
+
+ foreach(operation);
+ }
+}
diff --git a/services/core/java/com/android/server/location/GpsStatusListenerHelper.java b/services/core/java/com/android/server/location/GpsStatusListenerHelper.java
new file mode 100644
index 0000000..b741e75
--- /dev/null
+++ b/services/core/java/com/android/server/location/GpsStatusListenerHelper.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.location;
+
+import android.location.IGpsStatusListener;
+import android.os.RemoteException;
+
+/**
+ * Implementation of a handler for {@link IGpsStatusListener}.
+ */
+abstract class GpsStatusListenerHelper extends RemoteListenerHelper<IGpsStatusListener> {
+ public void onFirstFix(final int timeToFirstFix) {
+ Operation operation = new Operation() {
+ @Override
+ public void execute(IGpsStatusListener listener) throws RemoteException {
+ listener.onFirstFix(timeToFirstFix);
+ }
+ };
+
+ foreach(operation);
+ }
+
+ public void onStatusChanged(final boolean isNavigating) {
+ Operation operation = new Operation() {
+ @Override
+ public void execute(IGpsStatusListener listener) throws RemoteException {
+ if (isNavigating) {
+ listener.onGpsStarted();
+ } else {
+ listener.onGpsStopped();
+ }
+ }
+ };
+
+ foreach(operation);
+ }
+
+ public void onSvStatusChanged(
+ final int svCount,
+ final int[] prns,
+ final float[] snrs,
+ final float[] elevations,
+ final float[] azimuths,
+ final int ephemerisMask,
+ final int almanacMask,
+ final int usedInFixMask) {
+ Operation operation = new Operation() {
+ @Override
+ public void execute(IGpsStatusListener listener) throws RemoteException {
+ listener.onSvStatusChanged(
+ svCount,
+ prns,
+ snrs,
+ elevations,
+ azimuths,
+ ephemerisMask,
+ almanacMask,
+ usedInFixMask);
+ }
+ };
+
+ foreach(operation);
+ }
+
+ public void onNmeaReceived(final long timestamp, final String nmea) {
+ Operation operation = new Operation() {
+ @Override
+ public void execute(IGpsStatusListener listener) throws RemoteException {
+ listener.onNmeaReceived(timestamp, nmea);
+ }
+ };
+
+ foreach(operation);
+ }
+
+ private abstract class Operation implements ListenerOperation<IGpsStatusListener> { }
+}
diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java
new file mode 100644
index 0000000..79335f7
--- /dev/null
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.location;
+
+import com.android.internal.util.Preconditions;
+
+import android.annotation.NonNull;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+
+/**
+ * A helper class, that handles operations in remote listeners, and tracks for remote process death.
+ */
+abstract class RemoteListenerHelper<TListener extends IInterface> {
+ private static final String TAG = "RemoteListenerHelper";
+
+ private final HashMap<IBinder, LinkedListener> mListenerMap =
+ new HashMap<IBinder, LinkedListener>();
+
+ public boolean addListener(@NonNull TListener listener) {
+ Preconditions.checkNotNull(listener, "Attempted to register a 'null' listener.");
+
+ if (!isSupported()) {
+ Log.e(TAG, "Refused to add listener, the feature is not supported.");
+ return false;
+ }
+
+ IBinder binder = listener.asBinder();
+ LinkedListener deathListener = new LinkedListener(listener);
+ synchronized (mListenerMap) {
+ if (mListenerMap.containsKey(binder)) {
+ // listener already added
+ return true;
+ }
+
+ try {
+ binder.linkToDeath(deathListener, 0 /* flags */);
+ } catch (RemoteException e) {
+ // if the remote process registering the listener is already death, just swallow the
+ // exception and continue
+ Log.e(TAG, "Remote listener already died.", e);
+ return false;
+ }
+
+ mListenerMap.put(binder, deathListener);
+ if (mListenerMap.size() == 1) {
+ onFirstListenerAdded();
+ }
+ }
+
+ return true;
+ }
+
+ public boolean removeListener(@NonNull TListener listener) {
+ Preconditions.checkNotNull(listener, "Attempted to remove a 'null' listener.");
+
+ if (!isSupported()) {
+ Log.e(TAG, "Refused to remove listener, the feature is not supported.");
+ return false;
+ }
+
+ IBinder binder = listener.asBinder();
+ LinkedListener linkedListener;
+ synchronized (mListenerMap) {
+ linkedListener = mListenerMap.remove(binder);
+ if (mListenerMap.isEmpty() && linkedListener != null) {
+ onLastListenerRemoved();
+ }
+ }
+
+ if (linkedListener != null) {
+ binder.unlinkToDeath(linkedListener, 0 /* flags */);
+ }
+
+ return true;
+ }
+
+ protected abstract boolean isSupported();
+
+ protected void onFirstListenerAdded() {
+ // event triggered when the first listener has been added
+ }
+
+ protected void onLastListenerRemoved() {
+ // event triggered when the last listener has bee removed
+ }
+
+ protected interface ListenerOperation<TListener extends IInterface> {
+ void execute(TListener listener) throws RemoteException;
+ }
+
+ protected void foreach(ListenerOperation operation) {
+ Collection<LinkedListener> linkedListeners;
+ synchronized (mListenerMap) {
+ Collection<LinkedListener> values = mListenerMap.values();
+ linkedListeners = new ArrayList<LinkedListener>(values);
+ }
+
+ for (LinkedListener linkedListener : linkedListeners) {
+ TListener listener = linkedListener.getUnderlyingListener();
+ try {
+ operation.execute(listener);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in monitored listener.", e);
+ removeListener(listener);
+ }
+ }
+ }
+
+ private class LinkedListener implements IBinder.DeathRecipient {
+ private final TListener mListener;
+
+ public LinkedListener(@NonNull TListener listener) {
+ mListener = listener;
+ }
+
+ @NonNull
+ public TListener getUnderlyingListener() {
+ return mListener;
+ }
+
+ @Override
+ public void binderDied() {
+ Log.d(TAG, "Remote Listener died: " + mListener);
+ removeListener(mListener);
+ }
+ }
+}
diff --git a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
index 5bafb52..87626d0 100644
--- a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -52,6 +52,7 @@
static jmethodID method_reportGeofenceRemoveStatus;
static jmethodID method_reportGeofencePauseStatus;
static jmethodID method_reportGeofenceResumeStatus;
+static jmethodID method_reportMeasurementData;
static const GpsInterface* sGpsInterface = NULL;
static const GpsXtraInterface* sGpsXtraInterface = NULL;
@@ -60,6 +61,7 @@
static const GpsDebugInterface* sGpsDebugInterface = NULL;
static const AGpsRilInterface* sAGpsRilInterface = NULL;
static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
+static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL;
// temporary storage for GPS callbacks
static GpsSvStatus sGpsSvStatus;
@@ -441,6 +443,10 @@
"(II)V");
method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus",
"(II)V");
+ method_reportMeasurementData = env->GetMethodID(
+ clazz,
+ "reportMeasurementData",
+ "(Landroid/location/GpsMeasurementsEvent;)V");
err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0) {
@@ -464,6 +470,8 @@
(const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);
sGpsGeofencingInterface =
(const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE);
+ sGpsMeasurementInterface =
+ (const GpsMeasurementInterface*)sGpsInterface->get_extension(GPS_MEASUREMENT_INTERFACE);
}
}
@@ -851,42 +859,500 @@
return JNI_FALSE;
}
+static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
+ const char* doubleSignature = "(D)V";
+
+ jclass gpsClockClass = env->FindClass("android/location/GpsClock");
+ jmethodID gpsClockCtor = env->GetMethodID(gpsClockClass, "<init>", "()V");
+
+ jobject gpsClockObject = env->NewObject(gpsClockClass, gpsClockCtor);
+ GpsClockFlags flags = clock->flags;
+
+ if (flags & GPS_CLOCK_HAS_LEAP_SECOND) {
+ jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setLeapSecond", "(S)V");
+ env->CallObjectMethod(gpsClockObject, setterMethod, clock->leap_second);
+ }
+
+ jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setTimeInNs", "(J)V");
+ env->CallObjectMethod(gpsClockObject, setterMethod, clock->time_ns);
+
+ if (flags & GPS_CLOCK_HAS_TIME_UNCERTAINTY) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsClockClass,
+ "setTimeUncertaintyInNs",
+ doubleSignature);
+ env->CallObjectMethod(gpsClockObject, setterMethod, clock->time_uncertainty_ns);
+ }
+
+ if (flags & GPS_CLOCK_HAS_BIAS) {
+ jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setBiasInNs", doubleSignature);
+ env->CallObjectMethod(gpsClockObject, setterMethod, clock->bias_ns);
+ }
+
+ if (flags & GPS_CLOCK_HAS_BIAS_UNCERTAINTY) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsClockClass,
+ "setBiasUncertaintyInNs",
+ doubleSignature);
+ env->CallObjectMethod(gpsClockObject, setterMethod, clock->bias_uncertainty_ns);
+ }
+
+ if (flags & GPS_CLOCK_HAS_DRIFT) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsClockClass,
+ "setDriftInNsPerSec",
+ doubleSignature);
+ env->CallObjectMethod(gpsClockObject, setterMethod, clock->drift_nsps);
+ }
+
+ if (flags & GPS_CLOCK_HAS_DRIFT_UNCERTAINTY) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsClockClass,
+ "setDriftUncertaintyInNsPerSec",
+ doubleSignature);
+ env->CallObjectMethod(gpsClockObject, setterMethod, clock->drift_uncertainty_nsps);
+ }
+
+ return gpsClockObject;
+}
+
+static jobject translate_gps_measurement(
+ JNIEnv* env,
+ GpsMeasurement* measurement,
+ uint32_t time_ns) {
+ const char* shortSignature = "(S)V";
+ const char* longSignature = "(J)V";
+ const char* floatSignature = "(F)V";
+ const char* doubleSignature = "(D)V";
+
+ jclass gpsMeasurementClass = env->FindClass("android/location/GpsMeasurement");
+ jmethodID gpsMeasurementCtor = env->GetMethodID(gpsMeasurementClass, "<init>", "()V");
+
+ jobject gpsMeasurementObject = env->NewObject(gpsMeasurementClass, gpsMeasurementCtor);
+ GpsMeasurementFlags flags = measurement->flags;
+
+
+ jmethodID prnSetterMethod = env->GetMethodID(gpsMeasurementClass, "setPrn", "(B)V");
+ env->CallObjectMethod(gpsMeasurementObject, prnSetterMethod, measurement->prn);
+
+ jmethodID localTimeSetterMethod =
+ env->GetMethodID(gpsMeasurementClass, "setLocalTimeInNs", longSignature);
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ localTimeSetterMethod,
+ time_ns + measurement->time_offset_ns);
+
+ jmethodID receivedGpsTowSetterMethod =
+ env->GetMethodID(gpsMeasurementClass, "setReceivedGpsTowInNs", longSignature);
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ receivedGpsTowSetterMethod,
+ measurement->received_gps_tow_ns);
+
+ jmethodID cn0SetterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setCn0InDbHz",
+ doubleSignature);
+ env->CallObjectMethod(gpsMeasurementObject, cn0SetterMethod, measurement->c_n0_dbhz);
+
+ jmethodID pseudorangeRateSetterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setPseudorangeRateInMetersPerSec",
+ doubleSignature);
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ pseudorangeRateSetterMethod,
+ measurement->pseudorange_rate_mpersec);
+
+ jmethodID pseudorangeRateUncertaintySetterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setPseudorangeRateUncertaintyInMetersPerSec",
+ doubleSignature);
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ pseudorangeRateUncertaintySetterMethod,
+ measurement->pseudorange_rate_uncertainty_mpersec);
+
+ jmethodID accumulatedDeltaRangeSetterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setAccumulatedDeltaRangeInMeters",
+ doubleSignature);
+ env->CallVoidMethod(
+ gpsMeasurementObject,
+ accumulatedDeltaRangeSetterMethod,
+ measurement->accumulated_delta_range_m);
+
+ jmethodID accumulatedDeltaRangeUncertaintySetterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setAccumulatedDeltaRangeUncertaintyInMeters",
+ doubleSignature);
+ env->CallVoidMethod(
+ gpsMeasurementObject,
+ accumulatedDeltaRangeUncertaintySetterMethod,
+ measurement->accumulated_delta_range_uncertainty_m);
+
+
+ if (flags & GPS_MEASUREMENT_HAS_PSEUDORANGE) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setPseudorangeInMeters",
+ doubleSignature);
+ env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->pseudorange_m);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setPseudorangeUncertaintyInMeters",
+ doubleSignature);
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ setterMethod,
+ measurement->pseudorange_uncertainty_m);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_CODE_PHASE) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setCodePhaseInChips",
+ doubleSignature);
+ env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->code_phase_chips);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setCodePhaseUncertaintyInChips",
+ doubleSignature);
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ setterMethod,
+ measurement->code_phase_uncertainty_chips);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setCarrierFrequencyInHz",
+ floatSignature);
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ setterMethod,
+ measurement->carrier_frequency_hz);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_CARRIER_CYCLES) {
+ jmethodID setterMethod =
+ env->GetMethodID(gpsMeasurementClass, "setCarrierCycles", longSignature);
+ env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->carrier_cycles);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_CARRIER_PHASE) {
+ jmethodID setterMethod =
+ env->GetMethodID(gpsMeasurementClass, "setCarrierPhase", doubleSignature);
+ env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->carrier_phase);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setCarrierPhaseUncertainty",
+ doubleSignature);
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ setterMethod,
+ measurement->carrier_phase_uncertainty);
+ }
+
+ jmethodID lossOfLockSetterMethod =
+ env->GetMethodID(gpsMeasurementClass, "setLossOfLock", shortSignature);
+ env->CallObjectMethod(gpsMeasurementObject, lossOfLockSetterMethod, measurement->loss_of_lock);
+
+ if (flags & GPS_MEASUREMENT_HAS_BIT_NUMBER) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setBitNumber",
+ shortSignature);
+ env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->bit_number);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setTimeFromLastBitInNs",
+ longSignature);
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ setterMethod,
+ measurement->time_from_last_bit_ns);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_DOPPLER_SHIFT) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setDopplerShiftInHz",
+ doubleSignature);
+ env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->doppler_shift_hz);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setDopplerShiftUncertaintyInHz",
+ doubleSignature);
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ setterMethod,
+ measurement->doppler_shift_uncertainty_hz);
+ }
+
+ jmethodID multipathIndicatorSetterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setMultipathIndicator",
+ shortSignature);
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ multipathIndicatorSetterMethod,
+ measurement->multipath_indicator);
+
+ if (flags & GPS_MEASUREMENT_HAS_SNR) {
+ jmethodID setterMethod =
+ env->GetMethodID(gpsMeasurementClass, "setSnrInDb", doubleSignature);
+ env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->snr_db);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_ELEVATION) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setElevationInDeg",
+ doubleSignature);
+ env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->elevation_deg);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setElevationUncertaintyInDeg",
+ doubleSignature);
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ setterMethod,
+ measurement->elevation_uncertainty_deg);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_AZIMUTH) {
+ jmethodID setterMethod =
+ env->GetMethodID(gpsMeasurementClass, "setAzimuthInDeg", doubleSignature);
+ env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->azimuth_deg);
+ }
+
+ if (flags & GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY) {
+ jmethodID setterMethod = env->GetMethodID(
+ gpsMeasurementClass,
+ "setAzimuthUncertaintyInDeg",
+ doubleSignature);
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ setterMethod,
+ measurement->azimuth_uncertainty_deg);
+ }
+
+ jmethodID usedInFixSetterMethod = env->GetMethodID(gpsMeasurementClass, "setUsedInFix", "(Z)V");
+ env->CallObjectMethod(
+ gpsMeasurementObject,
+ usedInFixSetterMethod,
+ (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
+
+ return gpsMeasurementObject;
+}
+
+static jobjectArray translate_gps_measurements(JNIEnv* env, GpsData* data) {
+ size_t measurementCount = data->measurement_count;
+ if (measurementCount == 0) {
+ return NULL;
+ }
+
+ jclass gpsMeasurementClass = env->FindClass("android/location/GpsMeasurement");
+ jobjectArray gpsMeasurementArray = env->NewObjectArray(
+ measurementCount,
+ gpsMeasurementClass,
+ NULL /* initialElement */);
+
+ GpsMeasurement* gpsMeasurements = data->measurements;
+ for (uint16_t i = 0; i < measurementCount; ++i) {
+ jobject gpsMeasurement = translate_gps_measurement(
+ env,
+ &gpsMeasurements[i],
+ data->clock.time_ns);
+ env->SetObjectArrayElement(gpsMeasurementArray, i, gpsMeasurement);
+ env->DeleteLocalRef(gpsMeasurement);
+ }
+
+ env->DeleteLocalRef(gpsMeasurementClass);
+ return gpsMeasurementArray;
+}
+
+static void measurement_callback(GpsData* data) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (data == NULL) {
+ ALOGE("Invalid data provided to gps_measurement_callback");
+ return;
+ }
+
+ if (data->size == sizeof(GpsData)) {
+ jobject gpsClock = translate_gps_clock(env, &data->clock);
+ jobjectArray measurementArray = translate_gps_measurements(env, data);
+
+ jclass gpsMeasurementsEventClass = env->FindClass("android/location/GpsMeasurementsEvent");
+ jmethodID gpsMeasurementsEventCtor = env->GetMethodID(
+ gpsMeasurementsEventClass,
+ "<init>",
+ "(Landroid/location/GpsClock;[Landroid/location/GpsMeasurement;)V");
+
+ jobject gpsMeasurementsEvent = env->NewObject(
+ gpsMeasurementsEventClass,
+ gpsMeasurementsEventCtor,
+ gpsClock,
+ measurementArray);
+
+ env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData, gpsMeasurementsEvent);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ } else {
+ ALOGE("Invalid GpsData size found in gps_measurement_callback, size=%d", data->size);
+ return;
+ }
+}
+
+GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
+ sizeof(GpsMeasurementCallbacks),
+ measurement_callback,
+};
+
+static jboolean android_location_GpsLocationProvider_is_measurement_supported(
+ JNIEnv* env,
+ jobject obj) {
+ if (sGpsMeasurementInterface != NULL) {
+ return JNI_TRUE;
+ }
+ return JNI_FALSE;
+}
+
+static jboolean android_location_GpsLocationProvider_start_measurement_collection(
+ JNIEnv* env,
+ jobject obj) {
+ if (sGpsMeasurementInterface == NULL) {
+ ALOGE("Measurement interface is not available.");
+ return JNI_FALSE;
+ }
+
+ int result = sGpsMeasurementInterface->init(&sGpsMeasurementCallbacks);
+ if (result != GPS_GEOFENCE_OPERATION_SUCCESS) {
+ ALOGE("An error has been found on GpsMeasurementInterface::init, status=%d", result);
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+static jboolean android_location_GpsLocationProvider_stop_measurement_collection(
+ JNIEnv* env,
+ jobject obj) {
+ if (sGpsMeasurementInterface == NULL) {
+ ALOGE("Measurement interface not available");
+ return JNI_FALSE;
+ }
+
+ sGpsMeasurementInterface->close();
+ return JNI_TRUE;
+}
+
static JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
{"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported},
{"native_init", "()Z", (void*)android_location_GpsLocationProvider_init},
{"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup},
- {"native_set_position_mode", "(IIIII)Z", (void*)android_location_GpsLocationProvider_set_position_mode},
+ {"native_set_position_mode",
+ "(IIIII)Z",
+ (void*)android_location_GpsLocationProvider_set_position_mode},
{"native_start", "()Z", (void*)android_location_GpsLocationProvider_start},
{"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop},
- {"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data},
- {"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status},
+ {"native_delete_aiding_data",
+ "(I)V",
+ (void*)android_location_GpsLocationProvider_delete_aiding_data},
+ {"native_read_sv_status",
+ "([I[F[F[F[I)I",
+ (void*)android_location_GpsLocationProvider_read_sv_status},
{"native_read_nmea", "([BI)I", (void*)android_location_GpsLocationProvider_read_nmea},
{"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time},
- {"native_inject_location", "(DDF)V", (void*)android_location_GpsLocationProvider_inject_location},
+ {"native_inject_location",
+ "(DDF)V",
+ (void*)android_location_GpsLocationProvider_inject_location},
{"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra},
- {"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data},
- {"native_agps_data_conn_open", "(Ljava/lang/String;I)V", (void*)android_location_GpsLocationProvider_agps_data_conn_open},
- {"native_agps_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_closed},
- {"native_agps_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_failed},
- {"native_agps_set_id","(ILjava/lang/String;)V",(void*)android_location_GpsLocationProvider_agps_set_id},
- {"native_agps_set_ref_location_cellid","(IIIII)V",(void*)android_location_GpsLocationProvider_agps_set_reference_location_cellid},
- {"native_set_agps_server", "(ILjava/lang/String;I)V", (void*)android_location_GpsLocationProvider_set_agps_server},
- {"native_send_ni_response", "(II)V", (void*)android_location_GpsLocationProvider_send_ni_response},
- {"native_agps_ni_message", "([BI)V", (void *)android_location_GpsLocationProvider_agps_send_ni_message},
- {"native_get_internal_state", "()Ljava/lang/String;", (void*)android_location_GpsLocationProvider_get_internal_state},
- {"native_update_network_state", "(ZIZZLjava/lang/String;Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_update_network_state },
- {"native_is_geofence_supported", "()Z", (void*) android_location_GpsLocationProvider_is_geofence_supported},
- {"native_add_geofence", "(IDDDIIII)Z", (void *)android_location_GpsLocationProvider_add_geofence},
- {"native_remove_geofence", "(I)Z", (void *)android_location_GpsLocationProvider_remove_geofence},
+ {"native_inject_xtra_data",
+ "([BI)V",
+ (void*)android_location_GpsLocationProvider_inject_xtra_data},
+ {"native_agps_data_conn_open",
+ "(Ljava/lang/String;I)V",
+ (void*)android_location_GpsLocationProvider_agps_data_conn_open},
+ {"native_agps_data_conn_closed",
+ "()V",
+ (void*)android_location_GpsLocationProvider_agps_data_conn_closed},
+ {"native_agps_data_conn_failed",
+ "()V",
+ (void*)android_location_GpsLocationProvider_agps_data_conn_failed},
+ {"native_agps_set_id",
+ "(ILjava/lang/String;)V",
+ (void*)android_location_GpsLocationProvider_agps_set_id},
+ {"native_agps_set_ref_location_cellid",
+ "(IIIII)V",
+ (void*)android_location_GpsLocationProvider_agps_set_reference_location_cellid},
+ {"native_set_agps_server",
+ "(ILjava/lang/String;I)V",
+ (void*)android_location_GpsLocationProvider_set_agps_server},
+ {"native_send_ni_response",
+ "(II)V",
+ (void*)android_location_GpsLocationProvider_send_ni_response},
+ {"native_agps_ni_message",
+ "([BI)V",
+ (void *)android_location_GpsLocationProvider_agps_send_ni_message},
+ {"native_get_internal_state",
+ "()Ljava/lang/String;",
+ (void*)android_location_GpsLocationProvider_get_internal_state},
+ {"native_update_network_state",
+ "(ZIZZLjava/lang/String;Ljava/lang/String;)V",
+ (void*)android_location_GpsLocationProvider_update_network_state },
+ {"native_is_geofence_supported",
+ "()Z",
+ (void*) android_location_GpsLocationProvider_is_geofence_supported},
+ {"native_add_geofence",
+ "(IDDDIIII)Z",
+ (void *)android_location_GpsLocationProvider_add_geofence},
+ {"native_remove_geofence",
+ "(I)Z",
+ (void *)android_location_GpsLocationProvider_remove_geofence},
{"native_pause_geofence", "(I)Z", (void *)android_location_GpsLocationProvider_pause_geofence},
- {"native_resume_geofence", "(II)Z", (void *)android_location_GpsLocationProvider_resume_geofence}
+ {"native_resume_geofence",
+ "(II)Z",
+ (void *)android_location_GpsLocationProvider_resume_geofence},
+ {"native_is_measurement_supported",
+ "()Z",
+ (void*) android_location_GpsLocationProvider_is_measurement_supported},
+ {"native_start_measurement_collection",
+ "()Z",
+ (void*) android_location_GpsLocationProvider_start_measurement_collection},
+ {"native_stop_measurement_collection",
+ "()Z",
+ (void*) android_location_GpsLocationProvider_stop_measurement_collection}
};
int register_android_server_location_GpsLocationProvider(JNIEnv* env)
{
- return jniRegisterNativeMethods(env, "com/android/server/location/GpsLocationProvider", sMethods, NELEM(sMethods));
+ return jniRegisterNativeMethods(
+ env,
+ "com/android/server/location/GpsLocationProvider",
+ sMethods,
+ NELEM(sMethods));
}
} /* namespace android */