• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import android.location.GnssStatus;
4 import android.os.Build;
5 import androidx.annotation.Nullable;
6 import com.google.auto.value.AutoValue;
7 import java.util.ArrayList;
8 import java.util.Arrays;
9 import java.util.Collection;
10 import java.util.List;
11 import org.robolectric.util.ReflectionHelpers;
12 import org.robolectric.util.ReflectionHelpers.ClassParameter;
13 
14 /**
15  * Builder for {@link GnssStatus} objects, since they have a hidden constructor.
16  *
17  * @deprecated Use {@link GnssStatus.Builder} instead where possible.
18  */
19 @Deprecated
20 public final class GnssStatusBuilder {
21   /** Information about a single satellite in a {@link GnssStatus}. */
22   @AutoValue
23   public abstract static class GnssSatelliteInfo {
24     /**
25      * Gets the {@link GnssStatus#getConstellationType(int) GNSS constellation} of the satellite.
26      */
getConstellation()27     public abstract int getConstellation();
28 
29     /** Gets the {@link GnssStatus#getSvid(int) identification number} of the satellite. */
getSvid()30     public abstract int getSvid();
31 
32     /** Gets the {@link GnssStatus#getCn0DbHz(int) carrier-to-noise density} of the satellite. */
getCn0DbHz()33     public abstract float getCn0DbHz();
34 
35     /**
36      * Gets the {@link GnssStatus#getElevationDegrees(int) elevation} of the satellite, in degrees.
37      */
getElevation()38     public abstract float getElevation();
39 
40     /** Gets the {@link GnssStatus#getAzimuthDegrees(int) azimuth} of the satellite, in degrees. */
getAzimuth()41     public abstract float getAzimuth();
42 
43     /** Gets whether the satellite {@link GnssStatus#hasEphemerisData(int) has ephemeris data}. */
getHasEphemeris()44     public abstract boolean getHasEphemeris();
45 
46     /** Gets whether the satellite {@link GnssStatus#hasAlmanacData(int) has almanac data}. */
getHasAlmanac()47     public abstract boolean getHasAlmanac();
48 
49     /**
50      * Gets whether the satellite {@link GnssStatus#usedInFix(int) was used in the most recent
51      * position fix}.
52      */
isUsedInFix()53     public abstract boolean isUsedInFix();
54 
55     /**
56      * Gets the {@link GnssStatus#getCarrierFrequencyHz(int) carrier frequency} of the satellite, in
57      * Hz, if present; if {@code null}, indicates that the carrier frequency {@link
58      * GnssStatus#hasCarrierFrequencyHz(int) is not available}.
59      */
60     @Nullable
getCarrierFrequencyHz()61     public abstract Float getCarrierFrequencyHz();
62 
builder()63     public static Builder builder() {
64       return new AutoValue_GnssStatusBuilder_GnssSatelliteInfo.Builder();
65     }
66 
67     /** Builder for {@link GnssSatelliteInfo}. */
68     @AutoValue.Builder
69     public abstract static class Builder {
70       /**
71        * Sets the {@link GnssStatus#getConstellationType(int) GNSS constellation} of the satellite.
72        */
setConstellation(int constellation)73       public abstract Builder setConstellation(int constellation);
74 
75       /** Sets the {@link GnssStatus#getSvid(int) identification number} of the satellite. */
setSvid(int svid)76       public abstract Builder setSvid(int svid);
77 
78       /** Gets the {@link GnssStatus#getCn0DbHz(int) carrier-to-noise density} of the satellite. */
setCn0DbHz(float cn0DbHz)79       public abstract Builder setCn0DbHz(float cn0DbHz);
80 
81       /**
82        * Sets the {@link GnssStatus#getElevationDegrees(int) elevation} of the satellite, in
83        * degrees.
84        */
setElevation(float elevation)85       public abstract Builder setElevation(float elevation);
86 
87       /**
88        * Sets the {@link GnssStatus#getAzimuthDegrees(int) azimuth} of the satellite, in degrees.
89        */
setAzimuth(float azimuth)90       public abstract Builder setAzimuth(float azimuth);
91 
92       /** Sets whether the satellite {@link GnssStatus#hasEphemerisData(int) has ephemeris data}. */
setHasEphemeris(boolean hasEphemeris)93       public abstract Builder setHasEphemeris(boolean hasEphemeris);
94 
95       /** Sets whether the satellite {@link GnssStatus#hasAlmanacData(int) has almanac data}. */
setHasAlmanac(boolean hasAlmanac)96       public abstract Builder setHasAlmanac(boolean hasAlmanac);
97 
98       /**
99        * Sets whether the satellite {@link GnssStatus#usedInFix(int) was used in the most recent
100        * position fix}.
101        */
setUsedInFix(boolean usedInFix)102       public abstract Builder setUsedInFix(boolean usedInFix);
103 
104       /**
105        * Sets the {@link GnssStatus#getCarrierFrequencyHz(int) carrier frequency} of the satellite,
106        * in Hz, if present; if {@code null}, indicates that the carrier frequency {@link
107        * GnssStatus#hasCarrierFrequencyHz(int) is not available}.
108        */
setCarrierFrequencyHz(@ullable Float carrierFrequencyHz)109       public abstract Builder setCarrierFrequencyHz(@Nullable Float carrierFrequencyHz);
110 
111       /** Builds the {@link GnssSatelliteInfo}. */
build()112       public abstract GnssSatelliteInfo build();
113     }
114   }
115 
GnssStatusBuilder()116   private GnssStatusBuilder() {}
117 
118   /** Creates a new {@link GnssStatusBuilder}. */
create()119   public static GnssStatusBuilder create() {
120     return new GnssStatusBuilder();
121   }
122 
123   private final List<GnssSatelliteInfo> satelliteInfos = new ArrayList<>();
124 
125   /** Adds a satellite to the {@link GnssStatus} being built. */
addSatellite(GnssSatelliteInfo satelliteInfo)126   public GnssStatusBuilder addSatellite(GnssSatelliteInfo satelliteInfo) {
127     satelliteInfos.add(satelliteInfo);
128     return this;
129   }
130 
131   /** Adds a collection of satellites to the {@link GnssStatus} being built. */
addAllSatellites(Collection<GnssSatelliteInfo> satelliteInfos)132   public GnssStatusBuilder addAllSatellites(Collection<GnssSatelliteInfo> satelliteInfos) {
133     this.satelliteInfos.addAll(satelliteInfos);
134     return this;
135   }
136 
137   /** Builds the {@link GnssStatus} from the satellites previously added. */
build()138   public GnssStatus build() {
139     return createFrom(satelliteInfos);
140   }
141 
142   /** Convenience method to create a {@link GnssStatus} directly from known satellite info. */
buildFrom(GnssSatelliteInfo... satelliteInfos)143   public static GnssStatus buildFrom(GnssSatelliteInfo... satelliteInfos) {
144     return createFrom(Arrays.asList(satelliteInfos));
145   }
146 
147   private static final int GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA =
148       (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q)
149           ? ReflectionHelpers.getStaticField(GnssStatus.class, "GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA")
150           : 0;
151   private static final int GNSS_SV_FLAGS_HAS_ALMANAC_DATA =
152       (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q)
153           ? ReflectionHelpers.getStaticField(GnssStatus.class, "GNSS_SV_FLAGS_HAS_ALMANAC_DATA")
154           : 0;
155   private static final int GNSS_SV_FLAGS_USED_IN_FIX =
156       (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q)
157           ? ReflectionHelpers.getStaticField(GnssStatus.class, "GNSS_SV_FLAGS_USED_IN_FIX")
158           : 0;
159   private static final int GNSS_SV_FLAGS_HAS_CARRIER_FREQUENCY =
160       (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
161               && Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q)
162           ? ReflectionHelpers.getStaticField(
163               GnssStatus.class, "GNSS_SV_FLAGS_HAS_CARRIER_FREQUENCY")
164           : 0;
165   private static final boolean SUPPORTS_CARRIER_FREQUENCY =
166       (GNSS_SV_FLAGS_HAS_CARRIER_FREQUENCY != 0);
167 
168   private static final int SVID_SHIFT_WIDTH =
169       ReflectionHelpers.getStaticField(GnssStatus.class, "SVID_SHIFT_WIDTH");
170   private static final int CONSTELLATION_TYPE_SHIFT_WIDTH =
171       ReflectionHelpers.getStaticField(GnssStatus.class, "CONSTELLATION_TYPE_SHIFT_WIDTH");
172   private static final int CONSTELLATION_TYPE_MASK =
173       ReflectionHelpers.getStaticField(GnssStatus.class, "CONSTELLATION_TYPE_MASK");
174 
createFrom(List<GnssSatelliteInfo> satelliteInfos)175   private static GnssStatus createFrom(List<GnssSatelliteInfo> satelliteInfos) {
176     int svCount = satelliteInfos.size();
177     int[] svidWithFlags = new int[svCount];
178     float[] cn0DbHz = new float[svCount];
179     float[] elevations = new float[svCount];
180     float[] azimuths = new float[svCount];
181     float[] carrierFrequencies = new float[svCount];
182 
183     for (int i = 0; i < svCount; i++) {
184       GnssSatelliteInfo info = satelliteInfos.get(i);
185 
186       int packedSvid =
187           (info.getSvid() << SVID_SHIFT_WIDTH)
188               | (info.getConstellation() & CONSTELLATION_TYPE_MASK)
189                   << CONSTELLATION_TYPE_SHIFT_WIDTH;
190 
191       if (info.getHasEphemeris()) {
192         packedSvid |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA;
193       }
194       if (info.getHasAlmanac()) {
195         packedSvid |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA;
196       }
197       if (info.isUsedInFix()) {
198         packedSvid |= GNSS_SV_FLAGS_USED_IN_FIX;
199       }
200       if (SUPPORTS_CARRIER_FREQUENCY && info.getCarrierFrequencyHz() != null) {
201         packedSvid |= GNSS_SV_FLAGS_HAS_CARRIER_FREQUENCY;
202         carrierFrequencies[i] = info.getCarrierFrequencyHz();
203       }
204       svidWithFlags[i] = packedSvid;
205 
206       cn0DbHz[i] = info.getCn0DbHz();
207       elevations[i] = info.getElevation();
208       azimuths[i] = info.getAzimuth();
209     }
210 
211     List<ClassParameter<?>> classParameters = new ArrayList<>();
212     classParameters.add(ClassParameter.from(int.class, svCount));
213     classParameters.add(ClassParameter.from(int[].class, svidWithFlags));
214     classParameters.add(ClassParameter.from(float[].class, cn0DbHz));
215     classParameters.add(ClassParameter.from(float[].class, elevations));
216     classParameters.add(ClassParameter.from(float[].class, azimuths));
217 
218     if (SUPPORTS_CARRIER_FREQUENCY) {
219       classParameters.add(ClassParameter.from(float[].class, carrierFrequencies));
220     }
221 
222     return ReflectionHelpers.callConstructor(
223         GnssStatus.class, classParameters.toArray(new ClassParameter<?>[0]));
224   }
225 }
226