Java tutorial
/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package android.location; import android.annotation.TestApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.security.InvalidParameterException; /** * A class containing a GNSS satellite Navigation Message. */ public final class GnssNavigationMessage implements Parcelable { private static final byte[] EMPTY_ARRAY = new byte[0]; /** * The type of the GNSS Navigation Message * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef({ TYPE_UNKNOWN, TYPE_GPS_L1CA, TYPE_GPS_L2CNAV, TYPE_GPS_L5CNAV, TYPE_GPS_CNAV2, TYPE_GLO_L1CA, TYPE_BDS_D1, TYPE_BDS_D2, TYPE_GAL_I, TYPE_GAL_F }) public @interface GnssNavigationMessageType { } // The following enumerations must be in sync with the values declared in gps.h /** Message type unknown */ public static final int TYPE_UNKNOWN = 0; /** GPS L1 C/A message contained in the structure. */ public static final int TYPE_GPS_L1CA = 0x0101; /** GPS L2-CNAV message contained in the structure. */ public static final int TYPE_GPS_L2CNAV = 0x0102; /** GPS L5-CNAV message contained in the structure. */ public static final int TYPE_GPS_L5CNAV = 0x0103; /** GPS CNAV-2 message contained in the structure. */ public static final int TYPE_GPS_CNAV2 = 0x0104; /** Glonass L1 CA message contained in the structure. */ public static final int TYPE_GLO_L1CA = 0x0301; /** Beidou D1 message contained in the structure. */ public static final int TYPE_BDS_D1 = 0x0501; /** Beidou D2 message contained in the structure. */ public static final int TYPE_BDS_D2 = 0x0502; /** Galileo I/NAV message contained in the structure. */ public static final int TYPE_GAL_I = 0x0601; /** Galileo F/NAV message contained in the structure. */ public static final int TYPE_GAL_F = 0x0602; /** * The Navigation Message Status is 'unknown'. */ public static final int STATUS_UNKNOWN = 0; /** * The Navigation Message was received without any parity error in its navigation words. */ public static final int STATUS_PARITY_PASSED = (1 << 0); /** * The Navigation Message was received with words that failed parity check, but the receiver was * able to correct those words. */ public static final int STATUS_PARITY_REBUILT = (1 << 1); /** * Used for receiving GNSS satellite Navigation Messages from the GNSS engine. * * <p>You can implement this interface and call * {@link LocationManager#registerGnssNavigationMessageCallback}. */ public static abstract class Callback { /** * The status of GNSS Navigation Message event. * @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef({ STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_LOCATION_DISABLED }) public @interface GnssNavigationMessageStatus { } /** * The system does not support tracking of GNSS Navigation Messages. * * This status will not change in the future. */ public static final int STATUS_NOT_SUPPORTED = 0; /** * GNSS Navigation Messages are successfully being tracked, it will receive updates once * they are available. */ public static final int STATUS_READY = 1; /** * GNSS provider or Location is disabled, updated will not be received until they are * enabled. */ public static final int STATUS_LOCATION_DISABLED = 2; /** * Returns the latest collected GNSS Navigation Message. */ public void onGnssNavigationMessageReceived(GnssNavigationMessage event) { } /** * Returns the latest status of the GNSS Navigation Messages sub-system. */ public void onStatusChanged(@GnssNavigationMessageStatus int status) { } } // End enumerations in sync with gps.h private int mType; private int mSvid; private int mMessageId; private int mSubmessageId; private byte[] mData; private int mStatus; /** * @hide */ @TestApi public GnssNavigationMessage() { initialize(); } /** * Sets all contents to the values stored in the provided object. * @hide */ @TestApi public void set(GnssNavigationMessage navigationMessage) { mType = navigationMessage.mType; mSvid = navigationMessage.mSvid; mMessageId = navigationMessage.mMessageId; mSubmessageId = navigationMessage.mSubmessageId; mData = navigationMessage.mData; mStatus = navigationMessage.mStatus; } /** * Resets all the contents to its original state. * @hide */ @TestApi public void reset() { initialize(); } /** * Gets the type of the navigation message contained in the object. */ @GnssNavigationMessageType public int getType() { return mType; } /** * Sets the type of the navigation message. * @hide */ @TestApi public void setType(@GnssNavigationMessageType int value) { mType = value; } /** * Gets a string representation of the 'type'. * For internal and logging use only. */ private String getTypeString() { switch (mType) { case TYPE_UNKNOWN: return "Unknown"; case TYPE_GPS_L1CA: return "GPS L1 C/A"; case TYPE_GPS_L2CNAV: return "GPS L2-CNAV"; case TYPE_GPS_L5CNAV: return "GPS L5-CNAV"; case TYPE_GPS_CNAV2: return "GPS CNAV2"; case TYPE_GLO_L1CA: return "Glonass L1 C/A"; case TYPE_BDS_D1: return "Beidou D1"; case TYPE_BDS_D2: return "Beidou D2"; case TYPE_GAL_I: return "Galileo I"; case TYPE_GAL_F: return "Galileo F"; default: return "<Invalid:" + mType + ">"; } } /** * Gets the satellite ID. * * <p>Range varies by constellation. See definition at {@code GnssStatus#getSvid(int)} */ public int getSvid() { return mSvid; } /** * Sets the satellite ID. * @hide */ @TestApi public void setSvid(int value) { mSvid = value; } /** * Gets the Message identifier. * * <p>This provides an index to help with complete Navigation Message assembly. Similar * identifiers within the data bits themselves often supplement this information, in ways even * more specific to each message type; see the relevant satellite constellation ICDs for * details. * * <ul> * <li> For GPS L1 C/A subframe 4 and 5, this value corresponds to the 'frame id' of the * navigation message, in the range of 1-25 (Subframe 1, 2, 3 does not contain a 'frame id' and * this value can be set to -1.)</li> * <li> For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.</li> * <li> For BeiDou D1, this refers to the frame number in the range of 1-24</li> * <li> For Beidou D2, this refers to the frame number, in the range of 1-120</li> * <li> For Galileo F/NAV nominal frame structure, this refers to the subframe number, in the * range of 1-12</li> * <li> For Galileo I/NAV nominal frame structure, this refers to the subframe number in the * range of 1-24</li> * </ul> */ public int getMessageId() { return mMessageId; } /** * Sets the Message Identifier. * @hide */ @TestApi public void setMessageId(int value) { mMessageId = value; } /** * Gets the sub-message identifier, relevant to the {@link #getType()} of the message. * * <ul> * <li> For GPS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to the subframe * number of the navigation message, in the range of 1-5.</li> * <li>For Glonass L1 C/A, this refers to the String number, in the range from 1-15</li> * <li>For Galileo F/NAV, this refers to the page type in the range 1-6</li> * <li>For Galileo I/NAV, this refers to the word type in the range 1-10+</li> * <li>For Galileo in particular, the type information embedded within the data bits may be even * more useful in interpretation, than the nominal page and word types provided in this * field.</li> * </ul> */ public int getSubmessageId() { return mSubmessageId; } /** * Sets the Sub-message identifier. * @hide */ @TestApi public void setSubmessageId(int value) { mSubmessageId = value; } /** * Gets the data of the reported GPS message. * * <p>The bytes (or words) specified using big endian format (MSB first). * * <ul> * <li>For GPS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit words. Each * word (30 bits) should be fit into the last 30 bits in a 4-byte word (skip B31 and B32), with * MSB first, for a total of 40 bytes, covering a time period of 6, 6, and 0.6 seconds, * respectively.</li> * <li>For Glonass L1 C/A, each string contains 85 data bits, including the checksum. These * bits should be fit into 11 bytes, with MSB first (skip B86-B88), covering a time period of 2 * seconds.</li> * <li>For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols excluded). Each * word should be fit into 30-bytes, with MSB first (skip B239, B240), covering a time period of * 10 seconds.</li> * <li>For Galileo I/NAV, each page contains 2 page parts, even and odd, with a total of 2x114 = * 228 bits, (sync & tail excluded) that should be fit into 29 bytes, with MSB first (skip * B229-B232).</li> * </ul> */ @NonNull public byte[] getData() { return mData; } /** * Sets the data associated with the Navigation Message. * @hide */ @TestApi public void setData(byte[] value) { if (value == null) { throw new InvalidParameterException("Data must be a non-null array"); } mData = value; } /** * Gets the Status of the navigation message contained in the object. */ public int getStatus() { return mStatus; } /** * Sets the status of the navigation message. * @hide */ @TestApi public void setStatus(int value) { mStatus = value; } /** * Gets a string representation of the 'status'. * For internal and logging use only. */ private String getStatusString() { switch (mStatus) { case STATUS_UNKNOWN: return "Unknown"; case STATUS_PARITY_PASSED: return "ParityPassed"; case STATUS_PARITY_REBUILT: return "ParityRebuilt"; default: return "<Invalid:" + mStatus + ">"; } } public static final Creator<GnssNavigationMessage> CREATOR = new Creator<GnssNavigationMessage>() { @Override public GnssNavigationMessage createFromParcel(Parcel parcel) { GnssNavigationMessage navigationMessage = new GnssNavigationMessage(); navigationMessage.setType(parcel.readInt()); navigationMessage.setSvid(parcel.readInt()); navigationMessage.setMessageId(parcel.readInt()); navigationMessage.setSubmessageId(parcel.readInt()); int dataLength = parcel.readInt(); byte[] data = new byte[dataLength]; parcel.readByteArray(data); navigationMessage.setData(data); navigationMessage.setStatus(parcel.readInt()); return navigationMessage; } @Override public GnssNavigationMessage[] newArray(int size) { return new GnssNavigationMessage[size]; } }; @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(mType); parcel.writeInt(mSvid); parcel.writeInt(mMessageId); parcel.writeInt(mSubmessageId); parcel.writeInt(mData.length); parcel.writeByteArray(mData); parcel.writeInt(mStatus); } @Override public int describeContents() { return 0; } @Override public String toString() { final String format = " %-15s = %s\n"; StringBuilder builder = new StringBuilder("GnssNavigationMessage:\n"); builder.append(String.format(format, "Type", getTypeString())); builder.append(String.format(format, "Svid", mSvid)); builder.append(String.format(format, "Status", getStatusString())); builder.append(String.format(format, "MessageId", mMessageId)); builder.append(String.format(format, "SubmessageId", mSubmessageId)); builder.append(String.format(format, "Data", "{")); String prefix = " "; for (byte value : mData) { builder.append(prefix); builder.append(value); prefix = ", "; } builder.append(" }"); return builder.toString(); } private void initialize() { mType = TYPE_UNKNOWN; mSvid = 0; mMessageId = -1; mSubmessageId = -1; mData = EMPTY_ARRAY; mStatus = STATUS_UNKNOWN; } }