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