GnssNavigationMessage.java revision 2b67c07d82f59f9b776414576c21dd31ed9dac48
1/*
2 * Copyright (C) 2014 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.annotation.TestApi;
20import android.annotation.IntDef;
21import android.annotation.NonNull;
22import android.os.Parcel;
23import android.os.Parcelable;
24
25import java.lang.annotation.Retention;
26import java.lang.annotation.RetentionPolicy;
27import java.security.InvalidParameterException;
28
29/**
30 * A class containing a GNSS satellite Navigation Message.
31 */
32public final class GnssNavigationMessage implements Parcelable {
33
34    private static final byte[] EMPTY_ARRAY = new byte[0];
35
36    /**
37     * The type of the GPS Clock.
38     * @hide
39     */
40    @Retention(RetentionPolicy.SOURCE)
41    @IntDef({TYPE_UNKNOWN, TYPE_GPS_L1CA, TYPE_GPS_L2CNAV, TYPE_GPS_L5CNAV, TYPE_GPS_CNAV2,
42        TYPE_GLO_L1CA, TYPE_BDS_D1, TYPE_BDS_D2, TYPE_GAL_I, TYPE_GAL_F})
43    public @interface GnssNavigationMessageType {}
44
45    // The following enumerations must be in sync with the values declared in gps.h
46
47    /** Message type unknown */
48    public static final int TYPE_UNKNOWN = 0;
49    /** GPS L1 C/A message contained in the structure.  */
50    public static final int TYPE_GPS_L1CA = 0x0101;
51    /** GPS L2-CNAV message contained in the structure. */
52    public static final int TYPE_GPS_L2CNAV = 0x0102;
53    /** GPS L5-CNAV message contained in the structure. */
54    public static final int TYPE_GPS_L5CNAV = 0x0103;
55    /** GPS CNAV-2 message contained in the structure. */
56    public static final int TYPE_GPS_CNAV2 = 0x0104;
57    /** Glonass L1 CA message contained in the structure. */
58    public static final int TYPE_GLO_L1CA = 0x0301;
59    /** Beidou D1 message contained in the structure. */
60    public static final int TYPE_BDS_D1 = 0x0501;
61    /** Beidou D2 message contained in the structure. */
62    public static final int TYPE_BDS_D2 = 0x0502;
63    /** Galileo I/NAV message contained in the structure. */
64    public static final int TYPE_GAL_I = 0x0601;
65    /** Galileo F/NAV message contained in the structure. */
66    public static final int TYPE_GAL_F = 0x0602;
67
68    /**
69     * The Navigation Message Status is 'unknown'.
70     */
71    public static final int STATUS_UNKNOWN = 0;
72
73    /**
74     * The Navigation Message was received without any parity error in its navigation words.
75     */
76    public static final int STATUS_PARITY_PASSED = (1<<0);
77
78    /**
79     * The Navigation Message was received with words that failed parity check, but the receiver was
80     * able to correct those words.
81     */
82    public static final int STATUS_PARITY_REBUILT = (1<<1);
83
84    // End enumerations in sync with gps.h
85
86    private int mType;
87    private int mSvid;
88    private int mMessageId;
89    private int mSubmessageId;
90    private byte[] mData;
91    private int mStatus;
92
93    /**
94     * @hide
95     */
96    @TestApi
97    public GnssNavigationMessage() {
98        initialize();
99    }
100
101    /**
102     * Sets all contents to the values stored in the provided object.
103     * @hide
104     */
105    @TestApi
106    public void set(GnssNavigationMessage navigationMessage) {
107        mType = navigationMessage.mType;
108        mSvid = navigationMessage.mSvid;
109        mMessageId = navigationMessage.mMessageId;
110        mSubmessageId = navigationMessage.mSubmessageId;
111        mData = navigationMessage.mData;
112        mStatus = navigationMessage.mStatus;
113    }
114
115    /**
116     * Resets all the contents to its original state.
117     * @hide
118     */
119    @TestApi
120    public void reset() {
121        initialize();
122    }
123
124    /**
125     * Gets the type of the navigation message contained in the object.
126     */
127    @GnssNavigationMessageType
128    public int getType() {
129        return mType;
130    }
131
132    /**
133     * Sets the type of the navigation message.
134     * @hide
135     */
136    @TestApi
137    public void setType(@GnssNavigationMessageType int value) {
138        mType = value;
139    }
140
141    /**
142     * Gets a string representation of the 'type'.
143     * For internal and logging use only.
144     */
145    private String getTypeString() {
146        switch (mType) {
147            case TYPE_UNKNOWN:
148                return "Unknown";
149            case TYPE_GPS_L1CA:
150                return "GPS L1 C/A";
151            case TYPE_GPS_L2CNAV:
152                return "GPS L2-CNAV";
153            case TYPE_GPS_L5CNAV:
154                return "GPS L5-CNAV";
155            case TYPE_GPS_CNAV2:
156                return "GPS CNAV2";
157            case TYPE_GLO_L1CA:
158                return "Glonass L1 C/A";
159            case TYPE_BDS_D1:
160                return "Beidou D1";
161            case TYPE_BDS_D2:
162                return "Beidou D2";
163            case TYPE_GAL_I:
164                return "Galileo I";
165            case TYPE_GAL_F:
166                return "Galileo F";
167            default:
168                return "<Invalid:" + mType + ">";
169        }
170    }
171
172    /**
173     * Gets the Pseudo-random number.
174     * Range: [1, 32].
175     */
176    public int getSvid() {
177        return mSvid;
178    }
179
180    /**
181     * Sets the Pseud-random number.
182     * @hide
183     */
184    @TestApi
185    public void setSvid(int value) {
186        mSvid = value;
187    }
188
189    /**
190     * Gets the Message Identifier.
191     * It provides an index so the complete Navigation Message can be assembled. i.e. for L1 C/A
192     * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
193     * Subframe 1, 2, 3 does not contain a 'frame id' and this might be reported as -1.
194     */
195    public int getMessageId() {
196        return mMessageId;
197    }
198
199    /**
200     * Sets the Message Identifier.
201     * @hide
202     */
203    @TestApi
204    public void setMessageId(int value) {
205        mMessageId = value;
206    }
207
208    /**
209     * Gets the Sub-message Identifier.
210     * If required by {@link #getType()}, this value contains a sub-index within the current message
211     * (or frame) that is being transmitted. i.e. for L1 C/A the sub-message identifier corresponds
212     * to the sub-frame Id of the navigation message.
213     */
214    public int getSubmessageId() {
215        return mSubmessageId;
216    }
217
218    /**
219     * Sets the Sub-message identifier.
220     * @hide
221     */
222    @TestApi
223    public void setSubmessageId(int value) {
224        mSubmessageId = value;
225    }
226
227    /**
228     * Gets the data associated with the Navigation Message.
229     * The bytes (or words) specified using big endian format (MSB first).
230     */
231    @NonNull
232    public byte[] getData() {
233        return mData;
234    }
235
236    /**
237     * Sets the data associated with the Navigation Message.
238     * @hide
239     */
240    @TestApi
241    public void setData(byte[] value) {
242        if (value == null) {
243            throw new InvalidParameterException("Data must be a non-null array");
244        }
245
246        mData = value;
247    }
248
249    /**
250     * Gets the Status of the navigation message contained in the object.
251     */
252    public int getStatus() {
253        return mStatus;
254    }
255
256    /**
257     * Sets the status of the navigation message.
258     * @hide
259     */
260    @TestApi
261    public void setStatus(int value) {
262        mStatus = value;
263    }
264
265    /**
266     * Gets a string representation of the 'status'.
267     * For internal and logging use only.
268     */
269    private String getStatusString() {
270        switch (mStatus) {
271            case STATUS_UNKNOWN:
272                return "Unknown";
273            case STATUS_PARITY_PASSED:
274                return "ParityPassed";
275            case STATUS_PARITY_REBUILT:
276                return "ParityRebuilt";
277            default:
278                return "<Invalid:" + mStatus + ">";
279        }
280    }
281
282    public static final Creator<GnssNavigationMessage> CREATOR =
283            new Creator<GnssNavigationMessage>() {
284        @Override
285        public GnssNavigationMessage createFromParcel(Parcel parcel) {
286            GnssNavigationMessage navigationMessage = new GnssNavigationMessage();
287
288            navigationMessage.setType(parcel.readInt());
289            navigationMessage.setSvid(parcel.readInt());
290            navigationMessage.setMessageId(parcel.readInt());
291            navigationMessage.setSubmessageId(parcel.readInt());
292
293            int dataLength = parcel.readInt();
294            byte[] data = new byte[dataLength];
295            parcel.readByteArray(data);
296            navigationMessage.setData(data);
297
298            if (parcel.dataAvail() >= Integer.SIZE) {
299                int status = parcel.readInt();
300                navigationMessage.setStatus(status);
301            } else {
302                navigationMessage.setStatus(STATUS_UNKNOWN);
303            }
304
305            return navigationMessage;
306        }
307
308        @Override
309        public GnssNavigationMessage[] newArray(int size) {
310            return new GnssNavigationMessage[size];
311        }
312    };
313
314    @Override
315    public void writeToParcel(Parcel parcel, int flags) {
316        parcel.writeInt(mType);
317        parcel.writeInt(mSvid);
318        parcel.writeInt(mMessageId);
319        parcel.writeInt(mSubmessageId);
320        parcel.writeInt(mData.length);
321        parcel.writeByteArray(mData);
322        parcel.writeInt(mStatus);
323    }
324
325    @Override
326    public int describeContents() {
327        return 0;
328    }
329
330    @Override
331    public String toString() {
332        final String format = "   %-15s = %s\n";
333        StringBuilder builder = new StringBuilder("GnssNavigationMessage:\n");
334
335        builder.append(String.format(format, "Type", getTypeString()));
336        builder.append(String.format(format, "Svid", mSvid));
337        builder.append(String.format(format, "Status", getStatusString()));
338        builder.append(String.format(format, "MessageId", mMessageId));
339        builder.append(String.format(format, "SubmessageId", mSubmessageId));
340
341        builder.append(String.format(format, "Data", "{"));
342        String prefix = "        ";
343        for(byte value : mData) {
344            builder.append(prefix);
345            builder.append(value);
346            prefix = ", ";
347        }
348        builder.append(" }");
349
350        return builder.toString();
351    }
352
353    private void initialize() {
354        mType = TYPE_UNKNOWN;
355        mSvid = 0;
356        mMessageId = -1;
357        mSubmessageId = -1;
358        mData = EMPTY_ARRAY;
359        mStatus = STATUS_UNKNOWN;
360    }
361}
362