/* * 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.NonNull; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import java.security.InvalidParameterException; /** * A class containing a GPS satellite Navigation Message. * * @hide */ @SystemApi public class GpsNavigationMessage implements Parcelable { private static final byte[] EMPTY_ARRAY = new byte[0]; // The following enumerations must be in sync with the values declared in gps.h /** * The type of the navigation message is not available or unknown. */ public static final byte TYPE_UNKNOWN = 0; /** * The Navigation Message is of type L1 C/A. */ public static final byte TYPE_L1CA = 1; /** * The Navigation Message is of type L1-CNAV. */ public static final byte TYPE_L2CNAV = 2; /** * The Navigation Message is of type L5-CNAV. */ public static final byte TYPE_L5CNAV = 3; /** * The Navigation Message is of type CNAV-2. */ public static final byte TYPE_CNAV2 = 4; /** * The Navigation Message Status is 'unknown'. */ public static final short STATUS_UNKNOWN = 0; /** * The Navigation Message was received without any parity error in its navigation words. */ public static final short 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 short STATUS_PARITY_REBUILT = (1<<1); // End enumerations in sync with gps.h private byte mType; private byte mPrn; private short mMessageId; private short mSubmessageId; private byte[] mData; private short mStatus; GpsNavigationMessage() { initialize(); } /** * Sets all contents to the values stored in the provided object. */ public void set(GpsNavigationMessage navigationMessage) { mType = navigationMessage.mType; mPrn = navigationMessage.mPrn; mMessageId = navigationMessage.mMessageId; mSubmessageId = navigationMessage.mSubmessageId; mData = navigationMessage.mData; mStatus = navigationMessage.mStatus; } /** * Resets all the contents to its original state. */ public void reset() { initialize(); } /** * Gets the type of the navigation message contained in the object. */ public byte getType() { return mType; } /** * Sets the type of the navigation message. */ public void setType(byte 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_L1CA: return "L1 C/A"; case TYPE_L2CNAV: return "L2-CNAV"; case TYPE_L5CNAV: return "L5-CNAV"; case TYPE_CNAV2: return "CNAV-2"; default: return ""; } } /** * Gets the Pseudo-random number. * Range: [1, 32]. */ public byte getPrn() { return mPrn; } /** * Sets the Pseud-random number. */ public void setPrn(byte value) { mPrn = value; } /** * Gets the Message Identifier. * It provides an index so the complete Navigation Message can be assembled. i.e. for L1 C/A * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message. * Subframe 1, 2, 3 does not contain a 'frame id' and this might be reported as -1. */ public short getMessageId() { return mMessageId; } /** * Sets the Message Identifier. */ public void setMessageId(short value) { mMessageId = value; } /** * Gets the Sub-message Identifier. * If required by {@link #getType()}, this value contains a sub-index within the current message * (or frame) that is being transmitted. i.e. for L1 C/A the sub-message identifier corresponds * to the sub-frame Id of the navigation message. */ public short getSubmessageId() { return mSubmessageId; } /** * Sets the Sub-message identifier. */ public void setSubmessageId(short value) { mSubmessageId = value; } /** * Gets the data associated with the Navigation Message. * The bytes (or words) specified using big endian format (MSB first). */ @NonNull public byte[] getData() { return mData; } /** * Sets the data associated with the Navigation Message. */ 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 short getStatus() { return mStatus; } /** * Sets the status of the navigation message. */ public void setStatus(short 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 ""; } } public static final Creator CREATOR = new Creator() { @Override public GpsNavigationMessage createFromParcel(Parcel parcel) { GpsNavigationMessage navigationMessage = new GpsNavigationMessage(); navigationMessage.setType(parcel.readByte()); navigationMessage.setPrn(parcel.readByte()); navigationMessage.setMessageId((short) parcel.readInt()); navigationMessage.setSubmessageId((short) parcel.readInt()); int dataLength = parcel.readInt(); byte[] data = new byte[dataLength]; parcel.readByteArray(data); navigationMessage.setData(data); if (parcel.dataAvail() >= Integer.SIZE) { int status = parcel.readInt(); navigationMessage.setStatus((short) status); } else { navigationMessage.setStatus(STATUS_UNKNOWN); } return navigationMessage; } @Override public GpsNavigationMessage[] newArray(int size) { return new GpsNavigationMessage[size]; } }; public void writeToParcel(Parcel parcel, int flags) { parcel.writeByte(mType); parcel.writeByte(mPrn); 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("GpsNavigationMessage:\n"); builder.append(String.format(format, "Type", getTypeString())); builder.append(String.format(format, "Prn", mPrn)); 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; mPrn = 0; mMessageId = -1; mSubmessageId = -1; mData = EMPTY_ARRAY; mStatus = STATUS_UNKNOWN; } }