GpsStatus.java revision 9363b949a104786c87cd2cd18f206ff3c1957e5e
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.location; 18 19import android.util.SparseArray; 20 21import java.util.Iterator; 22import java.util.NoSuchElementException; 23 24 25/** 26 * This class represents the current state of the GPS engine. 27 * This class is used in conjunction with the {@link Listener} interface. 28 */ 29public final class GpsStatus { 30 private static final int NUM_SATELLITES = 255; 31 32 /* These package private values are modified by the LocationManager class */ 33 private int mTimeToFirstFix; 34 private final SparseArray<GpsSatellite> mSatellites = new SparseArray<>(); 35 36 private final class SatelliteIterator implements Iterator<GpsSatellite> { 37 private final int mSatellitesCount; 38 39 private int mIndex = 0; 40 41 SatelliteIterator() { 42 mSatellitesCount = mSatellites.size(); 43 } 44 45 @Override 46 public boolean hasNext() { 47 for (; mIndex < mSatellitesCount; ++mIndex) { 48 GpsSatellite satellite = mSatellites.valueAt(mIndex); 49 if (satellite.mValid) { 50 return true; 51 } 52 } 53 return false; 54 } 55 56 @Override 57 public GpsSatellite next() { 58 while (mIndex < mSatellitesCount) { 59 GpsSatellite satellite = mSatellites.valueAt(mIndex); 60 ++mIndex; 61 if (satellite.mValid) { 62 return satellite; 63 } 64 } 65 throw new NoSuchElementException(); 66 } 67 68 @Override 69 public void remove() { 70 throw new UnsupportedOperationException(); 71 } 72 } 73 74 private Iterable<GpsSatellite> mSatelliteList = new Iterable<GpsSatellite>() { 75 @Override 76 public Iterator<GpsSatellite> iterator() { 77 return new SatelliteIterator(); 78 } 79 }; 80 81 /** 82 * Event sent when the GPS system has started. 83 */ 84 public static final int GPS_EVENT_STARTED = 1; 85 86 /** 87 * Event sent when the GPS system has stopped. 88 */ 89 public static final int GPS_EVENT_STOPPED = 2; 90 91 /** 92 * Event sent when the GPS system has received its first fix since starting. 93 * Call {@link #getTimeToFirstFix()} to find the time from start to first fix. 94 */ 95 public static final int GPS_EVENT_FIRST_FIX = 3; 96 97 /** 98 * Event sent periodically to report GPS satellite status. 99 * Call {@link #getSatellites()} to retrieve the status for each satellite. 100 */ 101 public static final int GPS_EVENT_SATELLITE_STATUS = 4; 102 103 /** 104 * Used for receiving notifications when GPS status has changed. 105 */ 106 public interface Listener { 107 /** 108 * Called to report changes in the GPS status. 109 * The event number is one of: 110 * <ul> 111 * <li> {@link GpsStatus#GPS_EVENT_STARTED} 112 * <li> {@link GpsStatus#GPS_EVENT_STOPPED} 113 * <li> {@link GpsStatus#GPS_EVENT_FIRST_FIX} 114 * <li> {@link GpsStatus#GPS_EVENT_SATELLITE_STATUS} 115 * </ul> 116 * 117 * When this method is called, the client should call 118 * {@link LocationManager#getGpsStatus} to get additional 119 * status information. 120 * 121 * @param event event number for this notification 122 */ 123 void onGpsStatusChanged(int event); 124 } 125 126 /** 127 * Used for receiving NMEA sentences from the GPS. 128 * NMEA 0183 is a standard for communicating with marine electronic devices 129 * and is a common method for receiving data from a GPS, typically over a serial port. 130 * See <a href="http://en.wikipedia.org/wiki/NMEA_0183">NMEA 0183</a> for more details. 131 * You can implement this interface and call {@link LocationManager#addNmeaListener} 132 * to receive NMEA data from the GPS engine. 133 */ 134 public interface NmeaListener { 135 void onNmeaReceived(long timestamp, String nmea); 136 } 137 138 // For API-compat a public ctor() is not available 139 GpsStatus() {} 140 141 private void setStatus(int svCount, int[] svidWithFlags, float[] snrs, float[] elevations, 142 float[] azimuths) { 143 clearSatellites(); 144 for (int i = 0; i < svCount; i++) { 145 final int constellationType = 146 (svidWithFlags[i] >> GnssStatus.CONSTELLATION_TYPE_SHIFT_WIDTH) 147 & GnssStatus.CONSTELLATION_TYPE_MASK; 148 // Skip all non-GPS satellites. 149 if (constellationType != GnssStatus.CONSTELLATION_GPS) { 150 continue; 151 } 152 int prn = svidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH; 153 if (prn > 0 && prn <= NUM_SATELLITES) { 154 GpsSatellite satellite = mSatellites.get(prn); 155 if (satellite == null) { 156 satellite = new GpsSatellite(prn); 157 mSatellites.put(prn, satellite); 158 } 159 160 satellite.mValid = true; 161 satellite.mSnr = snrs[i]; 162 satellite.mElevation = elevations[i]; 163 satellite.mAzimuth = azimuths[i]; 164 satellite.mHasEphemeris = 165 (svidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0; 166 satellite.mHasAlmanac = 167 (svidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0; 168 satellite.mUsedInFix = 169 (svidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0; 170 } 171 } 172 } 173 174 /** 175 * Copies GPS satellites information from GnssStatus object. 176 * Since this method is only used within {@link LocationManager#getGpsStatus}, 177 * it does not need to be synchronized. 178 * @hide 179 */ 180 void setStatus(GnssStatus status, int timeToFirstFix) { 181 mTimeToFirstFix = timeToFirstFix; 182 setStatus(status.mSvCount, status.mSvidWithFlags, status.mSnrs, status.mElevations, 183 status.mAzimuths); 184 } 185 186 void setTimeToFirstFix(int ttff) { 187 mTimeToFirstFix = ttff; 188 } 189 190 /** 191 * Returns the time required to receive the first fix since the most recent 192 * restart of the GPS engine. 193 * 194 * @return time to first fix in milliseconds 195 */ 196 public int getTimeToFirstFix() { 197 return mTimeToFirstFix; 198 } 199 200 /** 201 * Returns an array of {@link GpsSatellite} objects, which represent the 202 * current state of the GPS engine. 203 * 204 * @return the list of satellites 205 */ 206 public Iterable<GpsSatellite> getSatellites() { 207 return mSatelliteList; 208 } 209 210 /** 211 * Returns the maximum number of satellites that can be in the satellite 212 * list that can be returned by {@link #getSatellites()}. 213 * 214 * @return the maximum number of satellites 215 */ 216 public int getMaxSatellites() { 217 return NUM_SATELLITES; 218 } 219 220 private void clearSatellites() { 221 int satellitesCount = mSatellites.size(); 222 for (int i = 0; i < satellitesCount; i++) { 223 GpsSatellite satellite = mSatellites.valueAt(i); 224 satellite.mValid = false; 225 } 226 } 227} 228