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