Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions location/java/android/location/GpsStatus.java
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,37 @@ void setStatus(GpsStatus status) {
mSatellites[i].setStatus(status.mSatellites[i]);
}
}

/**
* Used internally within {@link LocationManager} to copy GNSS status
* data from the Location Manager Service to its cached GnssStatus instance.
* Is synchronized to ensure that GNSS status updates are atomic.
*/
synchronized void setGnssStatus(int svCount, int[] prns, float[] snrs,
float[] elevations, float[] azimuths, boolean[] ephemeris,
boolean[] almanac, boolean[] usedInFix) {
int i;

for (i = 0; i < mSatellites.length; i++) {
mSatellites[i].mValid = false;
}

for (i = 0; i < svCount; i++) {
int prn = prns[i] - 1;
if (prn >= 0 && prn < mSatellites.length) {
GpsSatellite satellite = mSatellites[prn];

satellite.mValid = true;
satellite.mSnr = snrs[i];
satellite.mElevation = elevations[i];
satellite.mAzimuth = azimuths[i];
satellite.mHasEphemeris = ephemeris[i];
satellite.mHasAlmanac = almanac[i];
satellite.mUsedInFix = usedInFix[i];
}
}
}


void setTimeToFirstFix(int ttff) {
mTimeToFirstFix = ttff;
Expand Down
3 changes: 3 additions & 0 deletions location/java/android/location/IGpsStatusListener.aidl
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,8 @@ oneway interface IGpsStatusListener
void onSvStatusChanged(int svCount, in int[] prns, in float[] snrs,
in float[] elevations, in float[] azimuths,
int ephemerisMask, int almanacMask, int usedInFixMask);
void onGnssSvStatusChanged(int svCount, in int[] prns, in float[] snrs,
in float[] elevations, in float[] azimuths,
in boolean[] ephemeris, in boolean[] almanac, in boolean[] usedInFix);
void onNmeaReceived(long timestamp, String nmea);
}
16 changes: 16 additions & 0 deletions location/java/android/location/LocationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -1432,6 +1432,22 @@ public void onFirstFix(int ttff) {
}

@Override
public void onGnssSvStatusChanged(int svCount, int[] prns, float[] snrs,
float[] elevations, float[] azimuths, boolean[] ephemeris,
boolean[] almanac, boolean[] usedInFix) {
if (mListener != null) {
mGpsStatus.setGnssStatus(svCount, prns, snrs, elevations, azimuths,
ephemeris, almanac, usedInFix);

Message msg = Message.obtain();
msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS;
// remove any SV status messages already in the queue
mGpsHandler.removeMessages(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
mGpsHandler.sendMessage(msg);
}
}

@Override
public void onSvStatusChanged(int svCount, int[] prns, float[] snrs,
float[] elevations, float[] azimuths, int ephemerisMask,
int almanacMask, int usedInFixMask) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1677,7 +1677,56 @@ private void reportStatus(int status) {

/**
* called from native code to update SV info
*/
*/ private void reportGnssSvStatus() {
int svCount = native_read_gnss_sv_status(mGnssSvs, mGnssSnrs, mGnssSvElevations
, mGnssSvAzimuths, mGnssSvEphemeris, mGnssSvAlmanac, mGnssSvInFix);
mListenerHelper.onGnssSvStatusChanged(
svCount,
mGnssSvs,
mGnssSnrs,
mGnssSvElevations,
mGnssSvAzimuths,
mGnssSvEphemeris,
mGnssSvAlmanac,
mGnssSvInFix);

if (VERBOSE) {
Log.v(TAG, "GNSS SV count: " + svCount +
" ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
" almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
for (int i = 0; i < svCount; i++) {
Log.v(TAG, "sv: " + mGnssSvs[i] +
" snr: " + mGnssSnrs[i] / 10 +
" elev: " + mGnssSvElevations[i] +
" azimuth: " + mGnssSvAzimuths[i] +
((mGnssSvEphemeris[i]) ? " E" : " ") +
((mGnssSvAlmanac[i]) ? " A" : " ") +
((mGnssSvInFix[i]) ? " U" : " "));
}
}
int svFixCount = 0;
for (boolean value : mGnssSvInFix) {
if (value) {
svFixCount++;
}
}
updateStatus(mStatus, svFixCount);


if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
// send an intent to notify that the GPS is no longer receiving fixes.
Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
}
}

/**
* called from native code to update SV info
*/

private void reportSvStatus() {
int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
mListenerHelper.onSvStatusChanged(
Expand Down Expand Up @@ -2348,6 +2397,7 @@ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {

// for GPS SV statistics
private static final int MAX_SVS = 32;
private static final int MAX_GNSS_SVS = 256;
private static final int EPHEMERIS_MASK = 0;
private static final int ALMANAC_MASK = 1;
private static final int USED_FOR_FIX_MASK = 2;
Expand All @@ -2359,6 +2409,16 @@ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
private float mSvAzimuths[] = new float[MAX_SVS];
private int mSvMasks[] = new int[3];
private int mSvCount;

// preallocated arrays, to avoid memory allocation in reportStatus()
private int mGnssSvs[] = new int[MAX_GNSS_SVS];
private float mGnssSnrs[] = new float[MAX_GNSS_SVS];
private float mGnssSvElevations[] = new float[MAX_GNSS_SVS];
private float mGnssSvAzimuths[] = new float[MAX_GNSS_SVS];
private boolean mGnssSvEphemeris[] = new boolean[MAX_GNSS_SVS];
private boolean mGnssSvAlmanac[] = new boolean[MAX_GNSS_SVS];
private boolean mGnssSvInFix[] = new boolean[MAX_GNSS_SVS];

// preallocated to avoid memory allocation in reportNmea()
private byte[] mNmeaBuffer = new byte[120];

Expand All @@ -2379,6 +2439,9 @@ private native int native_read_sv_status(int[] svs, float[] snrs,
float[] elevations, float[] azimuths, int[] masks);
private native int native_read_nmea(byte[] buffer, int bufferSize);
private native void native_inject_location(double latitude, double longitude, float accuracy);
private native int native_read_gnss_sv_status(int[] svs, float[] snrs,
float[] elevations, float[] azimuths, boolean[] ephemeris, boolean[] almanac,
boolean[] infix);

// XTRA Support
private native void native_inject_time(long time, long timeReference, int uncertainty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,32 @@ public void execute(IGpsStatusListener listener) throws RemoteException {
foreach(operation);
}

public void onGnssSvStatusChanged(
final int svCount,
final int[] prns,
final float[] snrs,
final float[] elevations,
final float[] azimuths,
final boolean[] ephemeris,
final boolean[] almanac,
final boolean[] usedInFix) {
Operation operation = new Operation() {
@Override
public void execute(IGpsStatusListener listener) throws RemoteException {
listener.onGnssSvStatusChanged(
svCount,
prns,
snrs,
elevations,
azimuths,
ephemeris,
almanac,
usedInFix);
}
};

foreach(operation);
}
public void onNmeaReceived(final long timestamp, final String nmea) {
Operation operation = new Operation() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ static jobject mCallbacksObj = NULL;
static jmethodID method_reportLocation;
static jmethodID method_reportStatus;
static jmethodID method_reportSvStatus;
static jmethodID method_reportGnssSvStatus;
static jmethodID method_reportAGpsStatus;
static jmethodID method_reportNmea;
static jmethodID method_setEngineCapabilities;
Expand Down Expand Up @@ -69,6 +70,7 @@ static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;

// temporary storage for GPS callbacks
static GpsSvStatus sGpsSvStatus;
static GnssSvStatus sGnssSvStatus;
static const char* sNmeaString;
static int sNmeaStringLength;

Expand Down Expand Up @@ -110,6 +112,14 @@ static void sv_status_callback(GpsSvStatus* sv_status)
checkAndClearExceptionFromCallback(env, __FUNCTION__);
}

static void gnss_sv_status_callback(GnssSvStatus* sv_status)
{
JNIEnv* env = AndroidRuntime::getJNIEnv();
memcpy(&sGnssSvStatus, sv_status, sizeof(sGnssSvStatus));
env->CallVoidMethod(mCallbacksObj, method_reportGnssSvStatus);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
}

static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
{
JNIEnv* env = AndroidRuntime::getJNIEnv();
Expand Down Expand Up @@ -156,6 +166,7 @@ GpsCallbacks sGpsCallbacks = {
location_callback,
status_callback,
sv_status_callback,
gnss_sv_status_callback,
nmea_callback,
set_capabilities_callback,
acquire_wakelock_callback,
Expand Down Expand Up @@ -446,6 +457,7 @@ static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env,
method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
method_reportGnssSvStatus = env->GetMethodID(clazz, "reportGnssSvStatus", "()V");
method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
Expand Down Expand Up @@ -601,6 +613,12 @@ static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, job
jintArray maskArray)
{
// this should only be called from within a call to reportSvStatus

size_t status_size = sGpsSvStatus.size;
if (status_size != sizeof(GpsSvStatus)) {
jniThrowException(env, "java/lang/IllegalArgumentException ", "size wrong");
return (jint)0;
}

jint* prns = env->GetIntArrayElements(prnArray, 0);
jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
Expand All @@ -627,6 +645,48 @@ static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, job
return (jint) num_svs;
}

static jint android_location_GpsLocationProvider_read_gnss_sv_status(JNIEnv* env, jobject obj,
jintArray prnArray, jfloatArray snrArray, jfloatArray elevArray, jfloatArray azumArray,
jbooleanArray ephmArray,jbooleanArray almArray,jbooleanArray fixArray)
{
// this should only be called from within a call to reportGnssSvStatus
size_t status_size = sGnssSvStatus.size;
if (status_size != sizeof(GnssSvStatus)) {
jniThrowException(env, "java/lang/IllegalArgumentException ", "size wrong");
return (jint)0;
}

jint* prns = env->GetIntArrayElements(prnArray, 0);
jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
jboolean* ephm = env->GetBooleanArrayElements(ephmArray, 0);
jboolean* alm = env->GetBooleanArrayElements(almArray, 0);
jboolean* fix = env->GetBooleanArrayElements(fixArray, 0);

int num_svs = sGnssSvStatus.num_svs;
for (int i = 0; i < num_svs; i++) {
prns[i] = sGnssSvStatus.sv_list[i].prn;
snrs[i] = sGnssSvStatus.sv_list[i].snr;
elev[i] = sGnssSvStatus.sv_list[i].elevation;
azim[i] = sGnssSvStatus.sv_list[i].azimuth;
ephm[i] = sGnssSvStatus.sv_list[i].has_ephemeris;
alm[i] = sGnssSvStatus.sv_list[i].has_almanac;
fix[i] = sGnssSvStatus.sv_list[i].used_in_fix;
}

env->ReleaseIntArrayElements(prnArray, prns, 0);
env->ReleaseFloatArrayElements(snrArray, snrs, 0);
env->ReleaseFloatArrayElements(elevArray, elev, 0);
env->ReleaseFloatArrayElements(azumArray, azim, 0);
env->ReleaseBooleanArrayElements(ephmArray, ephm, 0);
env->ReleaseBooleanArrayElements(almArray, alm, 0);
env->ReleaseBooleanArrayElements(fixArray, fix, 0);

return (jint) num_svs;
}


static void android_location_GpsLocationProvider_agps_set_reference_location_cellid(JNIEnv* env,
jobject obj, jint type, jint mcc, jint mnc, jint lac, jint psc, jint cid)
{
Expand Down Expand Up @@ -1517,6 +1577,10 @@ static JNINativeMethod sMethods[] = {
{"native_configuration_update",
"(Ljava/lang/String;)V",
(void*)android_location_GpsLocationProvider_configuration_update},
{"native_read_gnss_sv_status",
"([I[F[F[F[Z[Z[Z)I",
(void*) android_location_GpsLocationProvider_read_gnss_sv_status},

};

int register_android_server_location_GpsLocationProvider(JNIEnv* env)
Expand Down