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