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