Update location framework to accept raw data from GPS HAL.
Change-Id: Ib4feca004b53fa89dcece4299974ab08913455a0
This commit is contained in:
@@ -288,6 +288,7 @@ LOCAL_SRC_FILES += \
|
||||
location/java/android/location/IFusedProvider.aidl \
|
||||
location/java/android/location/IGeocodeProvider.aidl \
|
||||
location/java/android/location/IGeofenceProvider.aidl \
|
||||
location/java/android/location/IGpsMeasurementsListener.aidl \
|
||||
location/java/android/location/IGpsStatusListener.aidl \
|
||||
location/java/android/location/IGpsStatusProvider.aidl \
|
||||
location/java/android/location/ILocationListener.aidl \
|
||||
|
||||
382
location/java/android/location/GpsClock.java
Normal file
382
location/java/android/location/GpsClock.java
Normal file
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* 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 android.location;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* A class containing a GPS clock timestamp.
|
||||
* It represents a measurement of the GPS receiver's clock.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class GpsClock implements Parcelable {
|
||||
// mandatory parameters
|
||||
private long mTimeInNs;
|
||||
|
||||
// optional parameters
|
||||
private boolean mHasLeapSecond;
|
||||
private short mLeapSecond;
|
||||
private boolean mHasTimeUncertaintyInNs;
|
||||
private double mTimeUncertaintyInNs;
|
||||
private boolean mHasBiasInNs;
|
||||
private double mBiasInNs;
|
||||
private boolean mHasBiasUncertaintyInNs;
|
||||
private double mBiasUncertaintyInNs;
|
||||
private boolean mHasDriftInNsPerSec;
|
||||
private double mDriftInNsPerSec;
|
||||
private boolean mHasDriftUncertaintyInNsPerSec;
|
||||
private double mDriftUncertaintyInNsPerSec;
|
||||
|
||||
GpsClock() {
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all contents to the values stored in the provided object.
|
||||
*/
|
||||
public void set(GpsClock clock) {
|
||||
mTimeInNs = clock.mTimeInNs;
|
||||
|
||||
mHasLeapSecond = clock.mHasLeapSecond;
|
||||
mLeapSecond = clock.mLeapSecond;
|
||||
mHasTimeUncertaintyInNs = clock.mHasTimeUncertaintyInNs;
|
||||
mTimeUncertaintyInNs = clock.mTimeUncertaintyInNs;
|
||||
mHasBiasInNs = clock.mHasBiasInNs;
|
||||
mBiasInNs = clock.mBiasInNs;
|
||||
mHasBiasUncertaintyInNs = clock.mHasBiasUncertaintyInNs;
|
||||
mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs;
|
||||
mHasDriftInNsPerSec = clock.mHasDriftInNsPerSec;
|
||||
mDriftInNsPerSec = clock.mDriftInNsPerSec;
|
||||
mHasDriftUncertaintyInNsPerSec = clock.mHasDriftUncertaintyInNsPerSec;
|
||||
mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all the contents to its original state.
|
||||
*/
|
||||
public void reset() {
|
||||
mTimeInNs = Long.MIN_VALUE;
|
||||
|
||||
resetLeapSecond();
|
||||
resetTimeUncertaintyInNs();
|
||||
resetBiasInNs();
|
||||
resetBiasUncertaintyInNs();
|
||||
resetDriftInNsPerSec();
|
||||
resetDriftUncertaintyInNsPerSec();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@link #getLeapSecond()} is available, false otherwise.
|
||||
*/
|
||||
public boolean hasLeapSecond() {
|
||||
return mHasLeapSecond;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the leap second associated with the clock's time.
|
||||
*
|
||||
* The value is only available if {@link #hasLeapSecond()} is true.
|
||||
*/
|
||||
public short getLeapSecond() {
|
||||
return mLeapSecond;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the leap second associated with the clock's time.
|
||||
*/
|
||||
public void setLeapSecond(short leapSecond) {
|
||||
mHasLeapSecond = true;
|
||||
mLeapSecond = leapSecond;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the leap second associated with the clock's time.
|
||||
*/
|
||||
public void resetLeapSecond() {
|
||||
mHasLeapSecond = false;
|
||||
mLeapSecond = Short.MIN_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the GPS clock Time in nanoseconds; it represents the uncorrected receiver's GPS time
|
||||
* since 0000Z, January 6, 1980; this is, including {@link #getBiasInNs()}.
|
||||
* The reported time includes {@link #getTimeUncertaintyInNs()}.
|
||||
*/
|
||||
public long getTimeInNs() {
|
||||
return mTimeInNs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the GPS clock Time in nanoseconds.
|
||||
*/
|
||||
public void setTimeInNs(long timeInNs) {
|
||||
mTimeInNs = timeInNs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@link #getTimeUncertaintyInNs()} is available, false otherwise.
|
||||
*/
|
||||
public boolean hasTimeUncertaintyInNs() {
|
||||
return mHasTimeUncertaintyInNs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clock's time Uncertainty (1-Sigma) in nanoseconds.
|
||||
*
|
||||
* The value is only available if {@link #hasTimeUncertaintyInNs()} is true.
|
||||
*/
|
||||
public double getTimeUncertaintyInNs() {
|
||||
return mTimeUncertaintyInNs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
|
||||
*/
|
||||
public void setTimeUncertaintyInNs(double timeUncertaintyInNs) {
|
||||
mHasTimeUncertaintyInNs = true;
|
||||
mTimeUncertaintyInNs = timeUncertaintyInNs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
|
||||
*/
|
||||
public void resetTimeUncertaintyInNs() {
|
||||
mHasTimeUncertaintyInNs = false;
|
||||
mTimeUncertaintyInNs = Double.NaN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@link #getBiasInNs()} is available, false otherwise.
|
||||
*/
|
||||
public boolean hasBiasInNs() {
|
||||
return mHasBiasInNs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clock's Bias in nanoseconds.
|
||||
* The sign of the value (if available), is defined by the following equation:
|
||||
* true time = time - bias.
|
||||
* The reported bias includes {@link #getBiasUncertaintyInNs()}.
|
||||
*
|
||||
* The value is only available if {@link #hasBiasInNs()} is true.
|
||||
*/
|
||||
public Double getBiasInNs() {
|
||||
return mBiasInNs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clock's Bias in nanoseconds.
|
||||
*/
|
||||
public void setBiasInNs(double biasInNs) {
|
||||
mHasBiasInNs = true;
|
||||
mBiasInNs = biasInNs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the clock's Bias in nanoseconds.
|
||||
*/
|
||||
public void resetBiasInNs() {
|
||||
mHasBiasInNs = false;
|
||||
mBiasInNs = Double.NaN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@link #getBiasUncertaintyInNs()} is available, false otherwise.
|
||||
*/
|
||||
public boolean hasBiasUncertaintyInNs() {
|
||||
return mHasBiasUncertaintyInNs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
|
||||
*
|
||||
* The value is only available if {@link #hasBiasUncertaintyInNs()} is true.
|
||||
*/
|
||||
public double getBiasUncertaintyInNs() {
|
||||
return mBiasUncertaintyInNs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
|
||||
*/
|
||||
public void setBiasUncertaintyInNs(double biasUncertaintyInNs) {
|
||||
mHasBiasUncertaintyInNs = true;
|
||||
mBiasUncertaintyInNs = biasUncertaintyInNs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
|
||||
*/
|
||||
public void resetBiasUncertaintyInNs() {
|
||||
mHasBiasUncertaintyInNs = false;
|
||||
mBiasUncertaintyInNs = Double.NaN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@link #getDriftInNsPerSec()} is available, false otherwise.
|
||||
*/
|
||||
public boolean hasDriftInNsPerSec() {
|
||||
return mHasDriftInNsPerSec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clock's Drift in nanoseconds per second.
|
||||
* A positive value indicates that the frequency is higher than the nominal frequency.
|
||||
* The reported drift includes {@link #getDriftUncertaintyInNsPerSec()}.
|
||||
*
|
||||
* The value is only available if {@link #hasDriftInNsPerSec()} is true.
|
||||
*/
|
||||
public double getDriftInNsPerSec() {
|
||||
return mDriftInNsPerSec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clock's Drift in nanoseconds per second.
|
||||
*/
|
||||
public void setDriftInNsPerSec(double driftInNsPerSec) {
|
||||
mHasDriftInNsPerSec = true;
|
||||
mDriftInNsPerSec = driftInNsPerSec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the clock's Drift in nanoseconds per second.
|
||||
*/
|
||||
public void resetDriftInNsPerSec() {
|
||||
mHasDriftInNsPerSec = false;
|
||||
mDriftInNsPerSec = Double.NaN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@link #getDriftUncertaintyInNsPerSec()} is available, false otherwise.
|
||||
*/
|
||||
public boolean hasDriftUncertaintyInNsPerSec() {
|
||||
return mHasDriftUncertaintyInNsPerSec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
|
||||
*
|
||||
* The value is only available if {@link #hasDriftUncertaintyInNsPerSec()} is true.
|
||||
*/
|
||||
public double getDriftUncertaintyInNsPerSec() {
|
||||
return mDriftUncertaintyInNsPerSec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
|
||||
*/
|
||||
public void setDriftUncertaintyInNsPerSec(double driftUncertaintyInNsPerSec) {
|
||||
mHasDriftUncertaintyInNsPerSec = true;
|
||||
mDriftUncertaintyInNsPerSec = driftUncertaintyInNsPerSec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
|
||||
*/
|
||||
public void resetDriftUncertaintyInNsPerSec() {
|
||||
mHasDriftUncertaintyInNsPerSec = false;
|
||||
mDriftUncertaintyInNsPerSec = Double.NaN;
|
||||
}
|
||||
|
||||
public static final Creator<GpsClock> CREATOR = new Creator<GpsClock>() {
|
||||
@Override
|
||||
public GpsClock createFromParcel(Parcel parcel) {
|
||||
GpsClock gpsClock = new GpsClock();
|
||||
gpsClock.mTimeInNs = parcel.readLong();
|
||||
|
||||
gpsClock.mHasLeapSecond = parcel.readInt() != 0;
|
||||
gpsClock.mLeapSecond = (short) parcel.readInt();
|
||||
gpsClock.mHasTimeUncertaintyInNs = parcel.readInt() != 0;
|
||||
gpsClock.mTimeUncertaintyInNs = parcel.readDouble();
|
||||
gpsClock.mHasBiasInNs = parcel.readInt() != 0;
|
||||
gpsClock.mBiasInNs = parcel.readDouble();
|
||||
gpsClock.mHasBiasUncertaintyInNs = parcel.readInt() != 0;
|
||||
gpsClock.mBiasUncertaintyInNs = parcel.readDouble();
|
||||
gpsClock.mHasDriftInNsPerSec = parcel.readInt() != 0;
|
||||
gpsClock.mDriftInNsPerSec = parcel.readDouble();
|
||||
gpsClock.mHasDriftUncertaintyInNsPerSec = parcel.readInt() != 0;
|
||||
gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble();
|
||||
|
||||
return gpsClock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GpsClock[] newArray(int size) {
|
||||
return new GpsClock[size];
|
||||
}
|
||||
};
|
||||
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeLong(mTimeInNs);
|
||||
|
||||
parcel.writeInt(mHasLeapSecond ? 1 : 0);
|
||||
parcel.writeInt(mLeapSecond);
|
||||
parcel.writeInt(mHasTimeUncertaintyInNs ? 1 : 0);
|
||||
parcel.writeDouble(mTimeUncertaintyInNs);
|
||||
parcel.writeInt(mHasBiasInNs ? 1 : 0);
|
||||
parcel.writeDouble(mBiasInNs);
|
||||
parcel.writeInt(mHasBiasUncertaintyInNs ? 1 : 0);
|
||||
parcel.writeDouble(mBiasUncertaintyInNs);
|
||||
parcel.writeInt(mHasDriftInNsPerSec ? 1 : 0);
|
||||
parcel.writeDouble(mDriftInNsPerSec);
|
||||
parcel.writeInt(mHasDriftUncertaintyInNsPerSec ? 1 : 0);
|
||||
parcel.writeDouble(mDriftUncertaintyInNsPerSec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final String format = " %-15s = %-25s %-26s = %s\n";
|
||||
StringBuilder builder = new StringBuilder("GpsClock:\n");
|
||||
|
||||
builder.append(String.format(
|
||||
format,
|
||||
"LeapSecond",
|
||||
mHasLeapSecond ? mLeapSecond : null,
|
||||
"",
|
||||
""));
|
||||
|
||||
builder.append(String.format(
|
||||
format,
|
||||
"TimeInNs",
|
||||
mTimeInNs,
|
||||
"TimeUncertaintyInNs",
|
||||
mHasTimeUncertaintyInNs ? mTimeUncertaintyInNs : null));
|
||||
|
||||
builder.append(String.format(
|
||||
format,
|
||||
"BiasInNs",
|
||||
mHasBiasInNs ? mBiasInNs : null,
|
||||
"BiasUncertaintyInNs",
|
||||
mHasBiasUncertaintyInNs ? mBiasUncertaintyInNs : null));
|
||||
|
||||
builder.append(String.format(
|
||||
format,
|
||||
"DriftInNsPerSec",
|
||||
mHasDriftInNsPerSec ? mDriftInNsPerSec : null,
|
||||
"DriftUncertaintyInNsPerSec",
|
||||
mHasDriftUncertaintyInNsPerSec ? mDriftUncertaintyInNsPerSec : null));
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
1222
location/java/android/location/GpsMeasurement.java
Normal file
1222
location/java/android/location/GpsMeasurement.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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 android.location;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* A handler class to manage transport listeners for {@link GpsMeasurementsEvent.Listener},
|
||||
* and post the events in a handler.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
class GpsMeasurementListenerTransport {
|
||||
private static final String TAG = "GpsMeasurementListenerTransport";
|
||||
|
||||
private final Context mContext;
|
||||
private final ILocationManager mLocationManager;
|
||||
|
||||
private final IGpsMeasurementsListener mListenerTransport = new ListenerTransport();
|
||||
private final HashSet<GpsMeasurementsEvent.Listener> mListeners =
|
||||
new HashSet<GpsMeasurementsEvent.Listener>();
|
||||
|
||||
public GpsMeasurementListenerTransport(Context context, ILocationManager locationManager) {
|
||||
mContext = context;
|
||||
mLocationManager = locationManager;
|
||||
}
|
||||
|
||||
public boolean add(@NonNull GpsMeasurementsEvent.Listener listener) {
|
||||
Preconditions.checkNotNull(listener);
|
||||
|
||||
synchronized (mListeners) {
|
||||
// we need to register with the service first, because we need to find out if the
|
||||
// service will actually support the request before we attempt anything
|
||||
if (mListeners.isEmpty()) {
|
||||
boolean registeredWithServer;
|
||||
try {
|
||||
registeredWithServer = mLocationManager.addGpsMeasurementsListener(
|
||||
mListenerTransport,
|
||||
mContext.getPackageName());
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error handling first listener.", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!registeredWithServer) {
|
||||
Log.e(TAG, "Unable to register listener transport.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mListeners.contains(listener)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void remove(@NonNull GpsMeasurementsEvent.Listener listener) {
|
||||
Preconditions.checkNotNull(listener);
|
||||
|
||||
synchronized (mListeners) {
|
||||
boolean removed = mListeners.remove(listener);
|
||||
|
||||
boolean isLastListener = removed && mListeners.isEmpty();
|
||||
if (isLastListener) {
|
||||
try {
|
||||
mLocationManager.removeGpsMeasurementsListener(mListenerTransport);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error handling last listener.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ListenerTransport extends IGpsMeasurementsListener.Stub {
|
||||
@Override
|
||||
public void onGpsMeasurementsReceived(final GpsMeasurementsEvent eventArgs) {
|
||||
Collection<GpsMeasurementsEvent.Listener> listeners;
|
||||
synchronized (mListeners) {
|
||||
listeners = new ArrayList<GpsMeasurementsEvent.Listener>(mListeners);
|
||||
}
|
||||
|
||||
for (final GpsMeasurementsEvent.Listener listener : listeners) {
|
||||
listener.onGpsMeasurementsReceived(eventArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
location/java/android/location/GpsMeasurementsEvent.aidl
Normal file
19
location/java/android/location/GpsMeasurementsEvent.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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 android.location;
|
||||
|
||||
parcelable GpsMeasurementsEvent;
|
||||
127
location/java/android/location/GpsMeasurementsEvent.java
Normal file
127
location/java/android/location/GpsMeasurementsEvent.java
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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 android.location;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* A class implementing a container for data associated with a measurement event.
|
||||
* Events are delivered to registered instances of {@link Listener}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class GpsMeasurementsEvent implements Parcelable {
|
||||
private final GpsClock mClock;
|
||||
private final Collection<GpsMeasurement> mReadOnlyMeasurements;
|
||||
|
||||
/**
|
||||
* Used for receiving GPS satellite measurements from the GPS engine.
|
||||
* Each measurement contains raw and computed data identifying a satellite.
|
||||
* You can implement this interface and call {@link LocationManager#addGpsMeasurementListener}.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface Listener {
|
||||
void onGpsMeasurementsReceived(GpsMeasurementsEvent eventArgs);
|
||||
}
|
||||
|
||||
public GpsMeasurementsEvent(GpsClock clock, GpsMeasurement[] measurements) {
|
||||
if (clock == null) {
|
||||
throw new InvalidParameterException("Parameter 'clock' must not be null.");
|
||||
}
|
||||
if (measurements == null || measurements.length == 0) {
|
||||
throw new InvalidParameterException(
|
||||
"Parameter 'measurements' must not be null or empty.");
|
||||
}
|
||||
|
||||
mClock = clock;
|
||||
Collection<GpsMeasurement> measurementCollection = Arrays.asList(measurements);
|
||||
mReadOnlyMeasurements = Collections.unmodifiableCollection(measurementCollection);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public GpsClock getClock() {
|
||||
return mClock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a read-only collection of measurements associated with the current event.
|
||||
*/
|
||||
@NonNull
|
||||
public Collection<GpsMeasurement> getMeasurements() {
|
||||
return mReadOnlyMeasurements;
|
||||
}
|
||||
|
||||
public static final Creator<GpsMeasurementsEvent> CREATOR =
|
||||
new Creator<GpsMeasurementsEvent>() {
|
||||
@Override
|
||||
public GpsMeasurementsEvent createFromParcel(Parcel in) {
|
||||
ClassLoader classLoader = getClass().getClassLoader();
|
||||
|
||||
GpsClock clock = in.readParcelable(classLoader);
|
||||
|
||||
int measurementsLength = in.readInt();
|
||||
GpsMeasurement[] measurementsArray = new GpsMeasurement[measurementsLength];
|
||||
in.readTypedArray(measurementsArray, GpsMeasurement.CREATOR);
|
||||
|
||||
return new GpsMeasurementsEvent(clock, measurementsArray);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GpsMeasurementsEvent[] newArray(int size) {
|
||||
return new GpsMeasurementsEvent[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeParcelable(mClock, flags);
|
||||
|
||||
GpsMeasurement[] measurementsArray = mReadOnlyMeasurements.toArray(new GpsMeasurement[0]);
|
||||
parcel.writeInt(measurementsArray.length);
|
||||
parcel.writeTypedArray(measurementsArray, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder("[ GpsMeasurementsEvent:\n\n");
|
||||
|
||||
builder.append(mClock.toString());
|
||||
builder.append("\n");
|
||||
|
||||
for (GpsMeasurement measurement : mReadOnlyMeasurements) {
|
||||
builder.append(measurement.toString());
|
||||
builder.append("\n");
|
||||
}
|
||||
|
||||
builder.append("]");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
26
location/java/android/location/IGpsMeasurementsListener.aidl
Normal file
26
location/java/android/location/IGpsMeasurementsListener.aidl
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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 android.location;
|
||||
|
||||
import android.location.GpsMeasurementsEvent;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
oneway interface IGpsMeasurementsListener {
|
||||
void onGpsMeasurementsReceived(in GpsMeasurementsEvent event);
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import android.location.Address;
|
||||
import android.location.Criteria;
|
||||
import android.location.GeocoderParams;
|
||||
import android.location.Geofence;
|
||||
import android.location.IGeocodeProvider;
|
||||
import android.location.IGpsMeasurementsListener;
|
||||
import android.location.IGpsStatusListener;
|
||||
import android.location.ILocationListener;
|
||||
import android.location.Location;
|
||||
@@ -60,6 +60,9 @@ interface ILocationManager
|
||||
|
||||
boolean sendNiResponse(int notifId, int userResponse);
|
||||
|
||||
boolean addGpsMeasurementsListener(in IGpsMeasurementsListener listener, in String packageName);
|
||||
boolean removeGpsMeasurementsListener(in IGpsMeasurementsListener listener);
|
||||
|
||||
// --- deprecated ---
|
||||
List<String> getAllProviders();
|
||||
List<String> getProviders(in Criteria criteria, boolean enabledOnly);
|
||||
|
||||
@@ -16,25 +16,23 @@
|
||||
|
||||
package android.location;
|
||||
|
||||
import com.android.internal.location.ProviderProperties;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
import java.lang.SecurityException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import com.android.internal.location.ProviderProperties;
|
||||
|
||||
/**
|
||||
* This class provides access to the system location services. These
|
||||
* services allow applications to obtain periodic updates of the
|
||||
@@ -60,6 +58,7 @@ public class LocationManager {
|
||||
|
||||
private final Context mContext;
|
||||
private final ILocationManager mService;
|
||||
private final GpsMeasurementListenerTransport mGpsMeasurementListenerTransport;
|
||||
private final HashMap<GpsStatus.Listener, GpsStatusListenerTransport> mGpsStatusListeners =
|
||||
new HashMap<GpsStatus.Listener, GpsStatusListenerTransport>();
|
||||
private final HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport> mNmeaListeners =
|
||||
@@ -310,6 +309,7 @@ public class LocationManager {
|
||||
public LocationManager(Context context, ILocationManager service) {
|
||||
mService = service;
|
||||
mContext = context;
|
||||
mGpsMeasurementListenerTransport = new GpsMeasurementListenerTransport(mContext, mService);
|
||||
}
|
||||
|
||||
private LocationProvider createProvider(String name, ProviderProperties properties) {
|
||||
@@ -1570,6 +1570,29 @@ public class LocationManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a GPS Measurement listener.
|
||||
*
|
||||
* @param listener a {@link android.location.GpsMeasurementsEvent.Listener} object to register.
|
||||
* @return {@code true} if the listener was successfully registered, {@code false} otherwise.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public boolean addGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
|
||||
return mGpsMeasurementListenerTransport.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a GPS Measurement listener.
|
||||
*
|
||||
* @param listener a {@link GpsMeasurementsEvent.Listener} object to remove.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
|
||||
mGpsMeasurementListenerTransport.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information about the current status of the GPS engine.
|
||||
* This should only be called from the {@link GpsStatus.Listener#onGpsStatusChanged}
|
||||
|
||||
@@ -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.Address;
|
||||
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.provider.Settings;
|
||||
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 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
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 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
addProviderLocked(gpsProvider);
|
||||
mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider);
|
||||
}
|
||||
mGpsMeasurementsProvider = gpsProvider.getGpsMeasurementsProvider();
|
||||
|
||||
/*
|
||||
Load package name(s) containing location provider support.
|
||||
@@ -1803,6 +1807,36 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@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) {
|
||||
|
||||
@@ -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.GeofenceHardware;
|
||||
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.BatteryStats;
|
||||
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.telephony.gsm.GsmCellLocation;
|
||||
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 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
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 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
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 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
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 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
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 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
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 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
* 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 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
* 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 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
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 @@ public class GpsLocationProvider implements LocationProviderInterface {
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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> { }
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ static jmethodID method_reportGeofenceAddStatus;
|
||||
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 GpsNiInterface* sGpsNiInterface = NULL;
|
||||
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 @@ static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env,
|
||||
"(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 @@ static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env,
|
||||
(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 @@ static jboolean android_location_GpsLocationProvider_resume_geofence(JNIEnv* env
|
||||
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 */
|
||||
|
||||
Reference in New Issue
Block a user