1 /* 2 * Copyright (C) 2013 Samsung System LSI 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 package com.android.bluetooth.map; 16 17 import java.io.UnsupportedEncodingException; 18 import java.nio.ByteBuffer; 19 import java.nio.ByteOrder; 20 import java.text.ParseException; 21 import java.text.SimpleDateFormat; 22 import java.util.Arrays; 23 import java.util.Date; 24 25 import android.util.Log; 26 27 import com.android.bluetooth.SignedLongLong; 28 29 /** 30 * This class encapsulates the appParams needed for MAP. 31 */ 32 public class BluetoothMapAppParams { 33 34 private static final String TAG = "BluetoothMapAppParams"; 35 36 private static final int MAX_LIST_COUNT = 0x01; 37 private static final int START_OFFSET = 0x02; 38 private static final int FILTER_MESSAGE_TYPE = 0x03; 39 private static final int FILTER_PERIOD_BEGIN = 0x04; 40 private static final int FILTER_PERIOD_END = 0x05; 41 private static final int FILTER_READ_STATUS = 0x06; 42 private static final int FILTER_RECIPIENT = 0x07; 43 private static final int FILTER_ORIGINATOR = 0x08; 44 private static final int FILTER_PRIORITY = 0x09; 45 private static final int ATTACHMENT = 0x0A; 46 private static final int TRANSPARENT = 0x0B; 47 private static final int RETRY = 0x0C; 48 private static final int NEW_MESSAGE = 0x0D; 49 private static final int NOTIFICATION_STATUS = 0x0E; 50 private static final int MAS_INSTANCE_ID = 0x0F; 51 private static final int PARAMETER_MASK = 0x10; 52 private static final int FOLDER_LISTING_SIZE = 0x11; 53 private static final int MESSAGE_LISTING_SIZE = 0x12; 54 private static final int SUBJECT_LENGTH = 0x13; 55 private static final int CHARSET = 0x14; 56 private static final int FRACTION_REQUEST = 0x15; 57 private static final int FRACTION_DELIVER = 0x16; 58 private static final int STATUS_INDICATOR = 0x17; 59 private static final int STATUS_VALUE = 0x18; 60 private static final int MSE_TIME = 0x19; 61 private static final int DATABASE_INDETIFIER = 0x1A; 62 private static final int CONVO_LIST_VER_COUNTER = 0x1B; 63 private static final int PRESENCE_AVAILABLE = 0x1C; 64 private static final int PRESENCE_TEXT = 0x1D; 65 private static final int LAST_ACTIVITY = 0x1E; 66 private static final int CHAT_STATE = 0x1F; 67 private static final int FILTER_CONVO_ID = 0x20; 68 private static final int CONVO_LISTING_SIZE = 0x21; 69 private static final int FILTER_PRESENCE = 0x22; 70 private static final int FILTER_UID_PRESENT = 0x23; 71 private static final int CHAT_STATE_CONVO_ID = 0x24; 72 private static final int FOLDER_VER_COUNTER = 0x25; 73 private static final int FILTER_MESSAGE_HANDLE = 0x26; 74 private static final int NOTIFICATION_FILTER = 0x27; 75 private static final int CONVO_PARAMETER_MASK = 0x28; 76 77 // Length defined for Application Parameters 78 private static final int MAX_LIST_COUNT_LEN = 0x02; //, 0x0000, 0xFFFF), 79 private static final int START_OFFSET_LEN = 0x02; //, 0x0000, 0xFFFF), 80 private static final int FILTER_MESSAGE_TYPE_LEN = 0x01; //, 0x0000, 0x000f), 81 private static final int FILTER_READ_STATUS_LEN = 0x01; //, 0x0000, 0x0002), 82 private static final int FILTER_PRIORITY_LEN = 0x01; //, 0x0000, 0x0002), 83 private static final int ATTACHMENT_LEN = 0x01; //, 0x0000, 0x0001), 84 private static final int TRANSPARENT_LEN = 0x01; //, 0x0000, 0x0001), 85 private static final int RETRY_LEN = 0x01; //, 0x0000, 0x0001), 86 private static final int NEW_MESSAGE_LEN = 0x01; //, 0x0000, 0x0001), 87 private static final int NOTIFICATION_STATUS_LEN = 0x01; //, 0x0000, 0xFFFF), 88 private static final int MAS_INSTANCE_ID_LEN = 0x01; //, 0x0000, 0x00FF), 89 private static final int PARAMETER_MASK_LEN = 0x04; //, 0x0000, 0x0000), 90 private static final int FOLDER_LISTING_SIZE_LEN = 0x02; //, 0x0000, 0xFFFF), 91 private static final int MESSAGE_LISTING_SIZE_LEN = 0x02; //, 0x0000, 0xFFFF), 92 private static final int SUBJECT_LENGTH_LEN = 0x01; //, 0x0000, 0x00FF), 93 private static final int CHARSET_LEN = 0x01; //, 0x0000, 0x0001), 94 private static final int FRACTION_REQUEST_LEN = 0x01; //, 0x0000, 0x0001), 95 private static final int FRACTION_DELIVER_LEN = 0x01; //, 0x0000, 0x0001), 96 private static final int STATUS_INDICATOR_LEN = 0x01; //, 0x0000, 0x0001), 97 private static final int STATUS_VALUE_LEN = 0x01; //, 0x0000, 0x0001), 98 private static final int DATABASE_INDETIFIER_LEN = 0x10; 99 private static final int CONVO_LIST_VER_COUNTER_LEN = 0x10; 100 private static final int PRESENCE_AVAILABLE_LEN = 0X01; 101 private static final int CHAT_STATE_LEN = 0x01; 102 private static final int CHAT_STATE_CONVO_ID_LEN = 0x10; 103 private static final int FILTER_CONVO_ID_LEN = 0x20; 104 private static final int CONVO_LISTING_SIZE_LEN = 0x02; 105 private static final int FILTER_PRESENCE_LEN = 0x01; 106 private static final int FILTER_UID_PRESENT_LEN = 0x01; 107 private static final int FOLDER_VER_COUNTER_LEN = 0x10; 108 private static final int FILTER_MESSAGE_HANDLE_LEN= 0x10; 109 private static final int NOTIFICATION_FILTER_LEN = 0x04; 110 private static final int CONVO_PARAMETER_MASK_LEN = 0x04; 111 112 // Default values 113 public static final int INVALID_VALUE_PARAMETER =-1; 114 public static final int NOTIFICATION_STATUS_NO = 0; 115 public static final int NOTIFICATION_STATUS_YES = 1; 116 public static final int STATUS_INDICATOR_READ = 0; 117 public static final int STATUS_INDICATOR_DELETED = 1; 118 public static final int STATUS_VALUE_YES = 1; 119 public static final int STATUS_VALUE_NO = 0; 120 public static final int CHARSET_NATIVE = 0; 121 public static final int CHARSET_UTF8 = 1; 122 public static final int FRACTION_REQUEST_FIRST = 0; 123 public static final int FRACTION_REQUEST_NEXT = 1; 124 public static final int FRACTION_DELIVER_MORE = 0; 125 public static final int FRACTION_DELIVER_LAST = 1; 126 127 public static final int FILTER_NO_SMS_GSM = 0x01; 128 public static final int FILTER_NO_SMS_CDMA = 0x02; 129 public static final int FILTER_NO_EMAIL = 0x04; 130 public static final int FILTER_NO_MMS = 0x08; 131 public static final int FILTER_NO_IM = 0x10; 132 public static final int FILTER_MSG_TYPE_MASK = 0x1F; 133 134 private int mMaxListCount = INVALID_VALUE_PARAMETER; 135 private int mStartOffset = INVALID_VALUE_PARAMETER; 136 private int mFilterMessageType = INVALID_VALUE_PARAMETER; 137 // It seems like these are not implemented... 138 private long mFilterPeriodBegin = INVALID_VALUE_PARAMETER; 139 private long mFilterPeriodEnd = INVALID_VALUE_PARAMETER; 140 private int mFilterReadStatus = INVALID_VALUE_PARAMETER; 141 private String mFilterRecipient = null; 142 private String mFilterOriginator = null; 143 private int mFilterPriority = INVALID_VALUE_PARAMETER; 144 private int mAttachment = INVALID_VALUE_PARAMETER; 145 private int mTransparent = INVALID_VALUE_PARAMETER; 146 private int mRetry = INVALID_VALUE_PARAMETER; 147 private int mNewMessage = INVALID_VALUE_PARAMETER; 148 private int mNotificationStatus = INVALID_VALUE_PARAMETER; 149 private long mNotificationFilter = INVALID_VALUE_PARAMETER; 150 private int mMasInstanceId = INVALID_VALUE_PARAMETER; 151 private long mParameterMask = INVALID_VALUE_PARAMETER; 152 private int mFolderListingSize = INVALID_VALUE_PARAMETER; 153 private int mMessageListingSize = INVALID_VALUE_PARAMETER; 154 private int mConvoListingSize = INVALID_VALUE_PARAMETER; 155 private int mSubjectLength = INVALID_VALUE_PARAMETER; 156 private int mCharset = INVALID_VALUE_PARAMETER; 157 private int mFractionRequest = INVALID_VALUE_PARAMETER; 158 private int mFractionDeliver = INVALID_VALUE_PARAMETER; 159 private int mStatusIndicator = INVALID_VALUE_PARAMETER; 160 private int mStatusValue = INVALID_VALUE_PARAMETER; 161 private long mMseTime = INVALID_VALUE_PARAMETER; 162 // TODO: Change to use SignedLongLong? 163 private long mConvoListingVerCounterLow = INVALID_VALUE_PARAMETER; 164 private long mConvoListingVerCounterHigh = INVALID_VALUE_PARAMETER; 165 private long mDatabaseIdentifierLow = INVALID_VALUE_PARAMETER; 166 private long mDatabaseIdentifierHigh = INVALID_VALUE_PARAMETER; 167 private long mFolderVerCounterLow = INVALID_VALUE_PARAMETER; 168 private long mFolderVerCounterHigh = INVALID_VALUE_PARAMETER; 169 private int mPresenceAvailability = INVALID_VALUE_PARAMETER; 170 private String mPresenceStatus = null; 171 private long mLastActivity = INVALID_VALUE_PARAMETER; 172 private int mChatState = INVALID_VALUE_PARAMETER; 173 private SignedLongLong mFilterConvoId = null; 174 private int mFilterPresence = INVALID_VALUE_PARAMETER; 175 private int mFilterUidPresent = INVALID_VALUE_PARAMETER; 176 private SignedLongLong mChatStateConvoId = null; 177 private long mFilterMsgHandle = INVALID_VALUE_PARAMETER; 178 private long mConvoParameterMask = INVALID_VALUE_PARAMETER; 179 180 /** 181 * Default constructor, used to build an application parameter object to be 182 * encoded. By default the member variables will be initialized to 183 * {@link INVALID_VALUE_PARAMETER} for values, and empty strings for String 184 * typed members. 185 */ BluetoothMapAppParams()186 public BluetoothMapAppParams() { 187 } 188 189 /** 190 * Creates an application parameter object based on a application parameter 191 * OBEX header. The content of the {@link appParam} byte array will be 192 * parsed, and its content will be stored in the member variables. 193 * {@link INVALID_VALUE_PARAMETER} can be used to determine if a value is 194 * set or not, where strings will be empty, if {@link appParam} did not 195 * contain the parameter. 196 * 197 * @param appParams 198 * the byte array containing the application parameters OBEX 199 * header 200 * @throws IllegalArgumentException 201 * when a parameter does not respect the valid ranges specified 202 * in the MAP spec. 203 * @throws ParseException 204 * if a parameter string if formated incorrectly. 205 */ BluetoothMapAppParams(final byte[] appParams)206 public BluetoothMapAppParams(final byte[] appParams) 207 throws IllegalArgumentException, ParseException { 208 ParseParams(appParams); 209 } 210 211 /** 212 * Parse an application parameter OBEX header stored in a byte array. 213 * 214 * @param appParams 215 * the byte array containing the application parameters OBEX 216 * header 217 * @throws IllegalArgumentException 218 * when a parameter does not respect the valid ranges specified 219 * in the MAP spec. 220 * @throws ParseException 221 * if a parameter string if formated incorrectly. 222 */ ParseParams(final byte[] appParams)223 private void ParseParams(final byte[] appParams) throws ParseException, 224 IllegalArgumentException { 225 int i = 0; 226 int tagId, tagLength; 227 ByteBuffer appParamBuf = ByteBuffer.wrap(appParams); 228 appParamBuf.order(ByteOrder.BIG_ENDIAN); 229 while (i < appParams.length) { 230 tagId = appParams[i++] & 0xff; // Convert to unsigned to support values above 127 231 tagLength = appParams[i++] & 0xff; // Convert to unsigned to support values above 127 232 switch (tagId) { 233 case MAX_LIST_COUNT: 234 if (tagLength != MAX_LIST_COUNT_LEN) { 235 Log.w(TAG, "MAX_LIST_COUNT: Wrong length received: " + tagLength 236 + " expected: " + MAX_LIST_COUNT_LEN); 237 } else { 238 setMaxListCount(appParamBuf.getShort(i) & 0xffff); // Make it unsigned 239 } 240 break; 241 case START_OFFSET: 242 if (tagLength != START_OFFSET_LEN) { 243 Log.w(TAG, "START_OFFSET: Wrong length received: " + tagLength + " expected: " 244 + START_OFFSET_LEN); 245 } else { 246 setStartOffset(appParamBuf.getShort(i) & 0xffff); // Make it unsigned 247 } 248 break; 249 case FILTER_MESSAGE_TYPE: 250 if (tagLength != FILTER_MESSAGE_TYPE_LEN) { 251 Log.w(TAG, "FILTER_MESSAGE_TYPE: Wrong length received: " + tagLength 252 + " expected: " + FILTER_MESSAGE_TYPE_LEN); 253 } else { 254 setFilterMessageType(appParams[i] & 0x1f); 255 } 256 break; 257 case FILTER_PERIOD_BEGIN: 258 if(tagLength != 0) { 259 setFilterPeriodBegin(new String(appParams, i, tagLength)); 260 } else { 261 Log.w(TAG, "FILTER_PERIOD_BEGIN: Wrong length received: " + tagLength + 262 " expected to be more than 0"); 263 } 264 break; 265 case FILTER_PERIOD_END: 266 if(tagLength != 0) { 267 setFilterPeriodEnd(new String(appParams, i, tagLength)); 268 } else { 269 Log.w(TAG, "FILTER_PERIOD_END: Wrong length received: " + tagLength + 270 " expected to be more than 0"); 271 } 272 break; 273 case FILTER_READ_STATUS: 274 if (tagLength != FILTER_READ_STATUS_LEN) { 275 Log.w(TAG, "FILTER_READ_STATUS: Wrong length received: " + tagLength + 276 " expected: " + FILTER_READ_STATUS_LEN); 277 } else { 278 setFilterReadStatus(appParams[i] & 0x03); // Lower two bits 279 } 280 break; 281 case FILTER_RECIPIENT: 282 if(tagLength != 0) { 283 setFilterRecipient(new String(appParams, i, tagLength)); 284 } else { 285 Log.w(TAG, "FILTER_RECIPIENT: Wrong length received: " + tagLength + 286 " expected to be more than 0"); 287 } 288 break; 289 case FILTER_ORIGINATOR: 290 if(tagLength != 0) { 291 setFilterOriginator(new String(appParams, i, tagLength)); 292 } else { 293 Log.w(TAG, "FILTER_ORIGINATOR: Wrong length received: " + tagLength + 294 " expected to be more than 0"); 295 } 296 break; 297 case FILTER_PRIORITY: 298 if (tagLength != FILTER_PRIORITY_LEN) { 299 Log.w(TAG, "FILTER_PRIORITY: Wrong length received: " + tagLength + 300 " expected: " + FILTER_PRIORITY_LEN); 301 } else { 302 setFilterPriority(appParams[i] & 0x03); // Lower two bits 303 } 304 break; 305 case ATTACHMENT: 306 if (tagLength != ATTACHMENT_LEN) { 307 Log.w(TAG, "ATTACHMENT: Wrong length received: " + tagLength + " expected: " 308 + ATTACHMENT_LEN); 309 } else { 310 setAttachment(appParams[i] & 0x01); // Lower bit 311 } 312 break; 313 case TRANSPARENT: 314 if (tagLength != TRANSPARENT_LEN) { 315 Log.w(TAG, "TRANSPARENT: Wrong length received: " + tagLength + " expected: " 316 + TRANSPARENT_LEN); 317 } else { 318 setTransparent(appParams[i] & 0x01); // Lower bit 319 } 320 break; 321 case RETRY: 322 if (tagLength != RETRY_LEN) { 323 Log.w(TAG, "RETRY: Wrong length received: " + tagLength + " expected: " 324 + RETRY_LEN); 325 } else { 326 setRetry(appParams[i] & 0x01); // Lower bit 327 } 328 break; 329 case NEW_MESSAGE: 330 if (tagLength != NEW_MESSAGE_LEN) { 331 Log.w(TAG, "NEW_MESSAGE: Wrong length received: " + tagLength + " expected: " 332 + NEW_MESSAGE_LEN); 333 } else { 334 setNewMessage(appParams[i] & 0x01); // Lower bit 335 } 336 break; 337 case NOTIFICATION_STATUS: 338 if (tagLength != NOTIFICATION_STATUS_LEN) { 339 Log.w(TAG, "NOTIFICATION_STATUS: Wrong length received: " + tagLength + 340 " expected: " + NOTIFICATION_STATUS_LEN); 341 } else { 342 setNotificationStatus(appParams[i] & 0x01); // Lower bit 343 } 344 break; 345 case NOTIFICATION_FILTER: 346 if (tagLength != NOTIFICATION_FILTER_LEN) { 347 Log.w(TAG, "NOTIFICATION_FILTER: Wrong length received: " + tagLength + 348 " expected: " + NOTIFICATION_FILTER_LEN); 349 } else { 350 setNotificationFilter(appParamBuf.getInt(i) & 0xffffffffL); // 4 bytes 351 } 352 break; 353 case MAS_INSTANCE_ID: 354 if (tagLength != MAS_INSTANCE_ID_LEN) { 355 Log.w(TAG, "MAS_INSTANCE_ID: Wrong length received: " + tagLength + 356 " expected: " + MAS_INSTANCE_ID_LEN); 357 } else { 358 setMasInstanceId(appParams[i] & 0xff); 359 } 360 break; 361 case PARAMETER_MASK: 362 if (tagLength != PARAMETER_MASK_LEN) { 363 Log.w(TAG, "PARAMETER_MASK: Wrong length received: " + tagLength + 364 " expected: " + PARAMETER_MASK_LEN); 365 } else { 366 setParameterMask(appParamBuf.getInt(i) & 0xffffffffL); // Make it unsigned 367 } 368 break; 369 case FOLDER_LISTING_SIZE: 370 if (tagLength != FOLDER_LISTING_SIZE_LEN) { 371 Log.w(TAG, "FOLDER_LISTING_SIZE: Wrong length received: " + tagLength + 372 " expected: " + FOLDER_LISTING_SIZE_LEN); 373 } else { 374 setFolderListingSize(appParamBuf.getShort(i) & 0xffff); // Make it unsigned 375 } 376 break; 377 case MESSAGE_LISTING_SIZE: 378 if (tagLength != MESSAGE_LISTING_SIZE_LEN) { 379 Log.w(TAG, "MESSAGE_LISTING_SIZE: Wrong length received: " + tagLength + 380 " expected: " + MESSAGE_LISTING_SIZE_LEN); 381 } else { 382 setMessageListingSize(appParamBuf.getShort(i) & 0xffff); // Make it unsigned 383 } 384 break; 385 case SUBJECT_LENGTH: 386 if (tagLength != SUBJECT_LENGTH_LEN) { 387 Log.w(TAG, "SUBJECT_LENGTH: Wrong length received: " + tagLength + 388 " expected: " + SUBJECT_LENGTH_LEN); 389 } else { 390 setSubjectLength(appParams[i] & 0xff); 391 } 392 break; 393 case CHARSET: 394 if (tagLength != CHARSET_LEN) { 395 Log.w(TAG, "CHARSET: Wrong length received: " + tagLength + " expected: " 396 + CHARSET_LEN); 397 } else { 398 setCharset(appParams[i] & 0x01); // Lower bit 399 } 400 break; 401 case FRACTION_REQUEST: 402 if (tagLength != FRACTION_REQUEST_LEN) { 403 Log.w(TAG, "FRACTION_REQUEST: Wrong length received: " + tagLength + 404 " expected: " + FRACTION_REQUEST_LEN); 405 } else { 406 setFractionRequest(appParams[i] & 0x01); // Lower bit 407 } 408 break; 409 case FRACTION_DELIVER: 410 if (tagLength != FRACTION_DELIVER_LEN) { 411 Log.w(TAG, "FRACTION_DELIVER: Wrong length received: " + tagLength + 412 " expected: " + FRACTION_DELIVER_LEN); 413 } else { 414 setFractionDeliver(appParams[i] & 0x01); // Lower bit 415 } 416 break; 417 case STATUS_INDICATOR: 418 if (tagLength != STATUS_INDICATOR_LEN) { 419 Log.w(TAG, "STATUS_INDICATOR: Wrong length received: " + tagLength + 420 " expected: " + STATUS_INDICATOR_LEN); 421 } else { 422 setStatusIndicator(appParams[i] & 0x01); // Lower bit 423 } 424 break; 425 case STATUS_VALUE: 426 if (tagLength != STATUS_VALUE_LEN) { 427 Log.w(TAG, "STATUS_VALUER: Wrong length received: " + tagLength + " expected: " 428 + STATUS_VALUE_LEN); 429 } else { 430 setStatusValue(appParams[i] & 0x01); // Lower bit 431 } 432 break; 433 case MSE_TIME: 434 setMseTime(new String(appParams, i, tagLength)); 435 break; 436 case DATABASE_INDETIFIER: 437 if((tagLength != DATABASE_INDETIFIER_LEN)){ 438 Log.w(TAG, "DATABASE_IDENTIFIER: Wrong length received: " + tagLength + 439 " expected: " + DATABASE_INDETIFIER_LEN); 440 } else { 441 setDatabaseIdentifier(appParamBuf.getLong(i)/*MSB*/, 442 appParamBuf.getLong(i+8)/*LSB*/); 443 } 444 break; 445 case CONVO_LIST_VER_COUNTER: 446 if((tagLength != CONVO_LIST_VER_COUNTER_LEN)){ 447 Log.w(TAG, "CONVO_LIST_VER_COUNTER: Wrong length received: " + tagLength + 448 " expected: " + CONVO_LIST_VER_COUNTER_LEN); 449 } else { 450 setConvoListingVerCounter(appParamBuf.getLong(i)/*MSB*/, 451 appParamBuf.getLong(i+8)/*LSB*/); 452 } 453 break; 454 case PRESENCE_AVAILABLE: 455 if((tagLength != PRESENCE_AVAILABLE_LEN)){ 456 Log.w(TAG, "PRESENCE_AVAILABLE: Wrong length received: " + tagLength + 457 " expected: " + PRESENCE_AVAILABLE_LEN); 458 } else { 459 setPresenceAvailability(appParams[i]); 460 } 461 break; 462 case PRESENCE_TEXT: 463 if(tagLength != 0) { 464 setPresenceStatus(new String(appParams, i, tagLength)); 465 } else 466 Log.w(TAG, "PRESENCE_STATUS: Wrong length received: " + tagLength + 467 " expected to be more than 0"); 468 break; 469 case LAST_ACTIVITY: 470 if(tagLength != 0) { 471 setLastActivity(new String(appParams, i, tagLength)); 472 } else 473 Log.w(TAG, "LAST_ACTIVITY: Wrong length received: " + tagLength + 474 " expected to be more than 0"); 475 break; 476 case CHAT_STATE: 477 if((tagLength != CHAT_STATE_LEN)){ 478 Log.w(TAG, "CHAT_STATE: Wrong length received: " + tagLength + 479 " expected: " + CHAT_STATE_LEN); 480 } else { 481 setChatState(appParams[i]); 482 } 483 break; 484 case FILTER_CONVO_ID: 485 if((tagLength != 0) && (tagLength <= FILTER_CONVO_ID_LEN)){ 486 setFilterConvoId(new String(appParams, i, tagLength)); 487 } else { 488 Log.w(TAG, "FILTER_CONVO_ID: Wrong length received: " + tagLength + 489 " expected: " + FILTER_CONVO_ID_LEN); 490 } 491 break; 492 case CONVO_LISTING_SIZE: 493 if(tagLength != CONVO_LISTING_SIZE_LEN){ 494 Log.w(TAG, "LISTING_SIZE: Wrong length received: "+ tagLength+" expected: "+ 495 CONVO_LISTING_SIZE_LEN); 496 497 } else { 498 setConvoListingSize(appParamBuf.getShort(i) & 0xffff); 499 } 500 break; 501 case FILTER_PRESENCE: 502 if((tagLength != FILTER_PRESENCE_LEN)){ 503 Log.w(TAG, "FILTER_PRESENCE: Wrong length received: " + tagLength + 504 " expected: " + FILTER_PRESENCE_LEN); 505 } else { 506 setFilterPresence(appParams[i]); 507 } 508 break; 509 case FILTER_UID_PRESENT: 510 if((tagLength != FILTER_UID_PRESENT_LEN)){ 511 Log.w(TAG, "FILTER_UID_PRESENT: Wrong length received: " + tagLength + 512 " expected: " + FILTER_UID_PRESENT_LEN); 513 } else { 514 setFilterUidPresent(appParams[i]&0x1); 515 } 516 break; 517 case CHAT_STATE_CONVO_ID: 518 if((tagLength != CHAT_STATE_CONVO_ID_LEN)){ 519 Log.w(TAG, "CHAT_STATE_CONVO_ID: Wrong length received: " + tagLength + 520 " expected: " + CHAT_STATE_CONVO_ID_LEN); 521 } else { 522 /* TODO: Is this correct convoId handling? */ 523 setChatStateConvoId(appParamBuf.getLong(i)/*MSB*/, 524 appParamBuf.getLong(i+8)/*LSB*/); 525 Log.d(TAG, "CHAT_STATE_CONVO_ID: convo id " + 526 "MSB=" + BluetoothMapUtils.getLongAsString(appParamBuf.getLong(i)) + 527 ", LSB(+8)=" + BluetoothMapUtils.getLongAsString(appParamBuf.getLong(i+8))); 528 529 } 530 break; 531 case FOLDER_VER_COUNTER: 532 break; 533 case FILTER_MESSAGE_HANDLE: 534 if((tagLength != 0 && tagLength <= FILTER_MESSAGE_HANDLE_LEN)){ 535 setFilterMsgHandle(new String(appParams, i, tagLength)); 536 } else { 537 Log.w(TAG, "FILTER_MESSAGE_HANDLE: Wrong length received: " + tagLength + 538 " expected: " + FILTER_MESSAGE_HANDLE_LEN); 539 } 540 541 break; 542 case CONVO_PARAMETER_MASK: 543 if (tagLength != CONVO_PARAMETER_MASK_LEN) { 544 Log.w(TAG, "CONVO_PARAMETER_MASK: Wrong length received: " + tagLength + 545 " expected: " + CONVO_PARAMETER_MASK_LEN); 546 } else { 547 setConvoParameterMask(appParamBuf.getInt(i) & 0xffffffffL); // Make it unsigned 548 } 549 break; 550 default: 551 // Just skip unknown Tags, no need to report error 552 Log.w(TAG, "Unknown TagId received ( 0x" + Integer.toString(tagId, 16) 553 + "), skipping..."); 554 break; 555 } 556 i += tagLength; // Offset to next TagId 557 } 558 } 559 560 /** 561 * Get the approximate length needed to store the appParameters in a byte 562 * array. 563 * 564 * @return the length in bytes 565 * @throws UnsupportedEncodingException 566 * if the platform does not support UTF-8 encoding. 567 */ getParamMaxLength()568 private int getParamMaxLength() throws UnsupportedEncodingException { 569 int length = 0; 570 length += 38 * 2; // tagId + tagLength 571 length += 33+4*16; // fixed sizes TODO: Update when spec is ready 572 length += getFilterPeriodBegin() == INVALID_VALUE_PARAMETER ? 0 : 20; 573 length += getFilterPeriodEnd() == INVALID_VALUE_PARAMETER ? 0 : 20; 574 if (getFilterRecipient() != null) 575 length += getFilterRecipient().getBytes("UTF-8").length; 576 if (getFilterOriginator() != null) 577 length += getFilterOriginator().getBytes("UTF-8").length; 578 length += getMseTime() == INVALID_VALUE_PARAMETER ? 0 : 20; 579 if(getPresenceStatus() != null) 580 length += getPresenceStatus().getBytes("UTF-8").length; 581 length += (getLastActivity() == INVALID_VALUE_PARAMETER) ? 0 : 20; 582 return length; 583 } 584 585 /** 586 * Encode the application parameter object to a byte array. 587 * 588 * @return a byte Array representation of the application parameter object. 589 * @throws UnsupportedEncodingException 590 * if the platform does not support UTF-8 encoding. 591 */ EncodeParams()592 public byte[] EncodeParams() throws UnsupportedEncodingException { 593 ByteBuffer appParamBuf = ByteBuffer.allocate(getParamMaxLength()); 594 appParamBuf.order(ByteOrder.BIG_ENDIAN); 595 byte[] retBuf; 596 597 if (getMaxListCount() != INVALID_VALUE_PARAMETER) { 598 appParamBuf.put((byte) MAX_LIST_COUNT); 599 appParamBuf.put((byte) MAX_LIST_COUNT_LEN); 600 appParamBuf.putShort((short) getMaxListCount()); 601 } 602 if (getStartOffset() != INVALID_VALUE_PARAMETER) { 603 appParamBuf.put((byte) START_OFFSET); 604 appParamBuf.put((byte) START_OFFSET_LEN); 605 appParamBuf.putShort((short) getStartOffset()); 606 } 607 if (getFilterMessageType() != INVALID_VALUE_PARAMETER) { 608 appParamBuf.put((byte) FILTER_MESSAGE_TYPE); 609 appParamBuf.put((byte) FILTER_MESSAGE_TYPE_LEN); 610 appParamBuf.put((byte) getFilterMessageType()); 611 } 612 if (getFilterPeriodBegin() != INVALID_VALUE_PARAMETER) { 613 appParamBuf.put((byte) FILTER_PERIOD_BEGIN); 614 appParamBuf.put((byte) getFilterPeriodBeginString().getBytes("UTF-8").length); 615 appParamBuf.put(getFilterPeriodBeginString().getBytes("UTF-8")); 616 } 617 if (getFilterPeriodEnd() != INVALID_VALUE_PARAMETER) { 618 appParamBuf.put((byte) FILTER_PERIOD_END); 619 appParamBuf.put((byte) getFilterPeriodEndString().getBytes("UTF-8").length); 620 appParamBuf.put(getFilterPeriodEndString().getBytes("UTF-8")); 621 } 622 if (getFilterReadStatus() != INVALID_VALUE_PARAMETER) { 623 appParamBuf.put((byte) FILTER_READ_STATUS); 624 appParamBuf.put((byte) FILTER_READ_STATUS_LEN); 625 appParamBuf.put((byte) getFilterReadStatus()); 626 } 627 if (getFilterRecipient() != null) { 628 appParamBuf.put((byte) FILTER_RECIPIENT); 629 appParamBuf.put((byte) getFilterRecipient().getBytes("UTF-8").length); 630 appParamBuf.put(getFilterRecipient().getBytes("UTF-8")); 631 } 632 if (getFilterOriginator() != null) { 633 appParamBuf.put((byte) FILTER_ORIGINATOR); 634 appParamBuf.put((byte) getFilterOriginator().getBytes("UTF-8").length); 635 appParamBuf.put(getFilterOriginator().getBytes("UTF-8")); 636 } 637 if (getFilterPriority() != INVALID_VALUE_PARAMETER) { 638 appParamBuf.put((byte) FILTER_PRIORITY); 639 appParamBuf.put((byte) FILTER_PRIORITY_LEN); 640 appParamBuf.put((byte) getFilterPriority()); 641 } 642 if (getAttachment() != INVALID_VALUE_PARAMETER) { 643 appParamBuf.put((byte) ATTACHMENT); 644 appParamBuf.put((byte) ATTACHMENT_LEN); 645 appParamBuf.put((byte) getAttachment()); 646 } 647 if (getTransparent() != INVALID_VALUE_PARAMETER) { 648 appParamBuf.put((byte) TRANSPARENT); 649 appParamBuf.put((byte) TRANSPARENT_LEN); 650 appParamBuf.put((byte) getTransparent()); 651 } 652 if (getRetry() != INVALID_VALUE_PARAMETER) { 653 appParamBuf.put((byte) RETRY); 654 appParamBuf.put((byte) RETRY_LEN); 655 appParamBuf.put((byte) getRetry()); 656 } 657 if (getNewMessage() != INVALID_VALUE_PARAMETER) { 658 appParamBuf.put((byte) NEW_MESSAGE); 659 appParamBuf.put((byte) NEW_MESSAGE_LEN); 660 appParamBuf.put((byte) getNewMessage()); 661 } 662 if (getNotificationStatus() != INVALID_VALUE_PARAMETER) { 663 appParamBuf.put((byte) NOTIFICATION_STATUS); 664 appParamBuf.put((byte) NOTIFICATION_STATUS_LEN); 665 appParamBuf.putShort((short) getNotificationStatus()); 666 } 667 if (getNotificationFilter() != INVALID_VALUE_PARAMETER) { 668 appParamBuf.put((byte) NOTIFICATION_FILTER); 669 appParamBuf.put((byte) NOTIFICATION_FILTER_LEN); 670 appParamBuf.putInt((int) getNotificationFilter()); 671 } 672 if (getMasInstanceId() != INVALID_VALUE_PARAMETER) { 673 appParamBuf.put((byte) MAS_INSTANCE_ID); 674 appParamBuf.put((byte) MAS_INSTANCE_ID_LEN); 675 appParamBuf.put((byte) getMasInstanceId()); 676 } 677 if (getParameterMask() != INVALID_VALUE_PARAMETER) { 678 appParamBuf.put((byte) PARAMETER_MASK); 679 appParamBuf.put((byte) PARAMETER_MASK_LEN); 680 appParamBuf.putInt((int) getParameterMask()); 681 } 682 if (getFolderListingSize() != INVALID_VALUE_PARAMETER) { 683 appParamBuf.put((byte) FOLDER_LISTING_SIZE); 684 appParamBuf.put((byte) FOLDER_LISTING_SIZE_LEN); 685 appParamBuf.putShort((short) getFolderListingSize()); 686 } 687 if (getMessageListingSize() != INVALID_VALUE_PARAMETER) { 688 appParamBuf.put((byte) MESSAGE_LISTING_SIZE); 689 appParamBuf.put((byte) MESSAGE_LISTING_SIZE_LEN); 690 appParamBuf.putShort((short) getMessageListingSize()); 691 } 692 if (getSubjectLength() != INVALID_VALUE_PARAMETER) { 693 appParamBuf.put((byte) SUBJECT_LENGTH); 694 appParamBuf.put((byte) SUBJECT_LENGTH_LEN); 695 appParamBuf.put((byte) getSubjectLength()); 696 } 697 if (getCharset() != INVALID_VALUE_PARAMETER) { 698 appParamBuf.put((byte) CHARSET); 699 appParamBuf.put((byte) CHARSET_LEN); 700 appParamBuf.put((byte) getCharset()); 701 } 702 if (getFractionRequest() != INVALID_VALUE_PARAMETER) { 703 appParamBuf.put((byte) FRACTION_REQUEST); 704 appParamBuf.put((byte) FRACTION_REQUEST_LEN); 705 appParamBuf.put((byte) getFractionRequest()); 706 } 707 if (getFractionDeliver() != INVALID_VALUE_PARAMETER) { 708 appParamBuf.put((byte) FRACTION_DELIVER); 709 appParamBuf.put((byte) FRACTION_DELIVER_LEN); 710 appParamBuf.put((byte) getFractionDeliver()); 711 } 712 if (getStatusIndicator() != INVALID_VALUE_PARAMETER) { 713 appParamBuf.put((byte) STATUS_INDICATOR); 714 appParamBuf.put((byte) STATUS_INDICATOR_LEN); 715 appParamBuf.put((byte) getStatusIndicator()); 716 } 717 if (getStatusValue() != INVALID_VALUE_PARAMETER) { 718 appParamBuf.put((byte) STATUS_VALUE); 719 appParamBuf.put((byte) STATUS_VALUE_LEN); 720 appParamBuf.put((byte) getStatusValue()); 721 } 722 if (getMseTime() != INVALID_VALUE_PARAMETER) { 723 appParamBuf.put((byte) MSE_TIME); 724 appParamBuf.put((byte) getMseTimeString().getBytes("UTF-8").length); 725 appParamBuf.put(getMseTimeString().getBytes("UTF-8")); 726 } 727 // Note: New for IM 728 if (getDatabaseIdentifier() != null) { 729 appParamBuf.put((byte)DATABASE_INDETIFIER); 730 appParamBuf.put((byte)DATABASE_INDETIFIER_LEN); 731 appParamBuf.put(getDatabaseIdentifier()); 732 } 733 if (getConvoListingVerCounter() != null) { 734 appParamBuf.put((byte)CONVO_LIST_VER_COUNTER); 735 appParamBuf.put((byte)CONVO_LIST_VER_COUNTER_LEN); 736 appParamBuf.put(getConvoListingVerCounter()); 737 } 738 if (getPresenceAvailability() != INVALID_VALUE_PARAMETER) { 739 appParamBuf.put((byte)PRESENCE_AVAILABLE); 740 appParamBuf.put((byte)PRESENCE_AVAILABLE_LEN); 741 appParamBuf.putInt((int)getPresenceAvailability()); 742 } 743 if (getPresenceStatus()!= null) { 744 appParamBuf.put((byte)PRESENCE_TEXT); 745 appParamBuf.put((byte)getPresenceStatus().getBytes("UTF-8").length); 746 appParamBuf.put(getPresenceStatus().getBytes()); 747 } 748 if (getLastActivity() != INVALID_VALUE_PARAMETER) { 749 appParamBuf.put((byte)LAST_ACTIVITY); 750 appParamBuf.put((byte)getLastActivityString().getBytes("UTF-8").length); 751 appParamBuf.put(getLastActivityString().getBytes()); 752 } 753 if (getChatState() != INVALID_VALUE_PARAMETER) { 754 appParamBuf.put((byte)CHAT_STATE); 755 appParamBuf.put((byte)CHAT_STATE_LEN); 756 appParamBuf.putShort((short)getChatState()); 757 } 758 if (getFilterConvoId() != null) { 759 appParamBuf.put((byte)FILTER_CONVO_ID); 760 appParamBuf.put((byte)FILTER_CONVO_ID_LEN); 761 appParamBuf.putLong(getFilterConvoId().getMostSignificantBits()); 762 appParamBuf.putLong(getFilterConvoId().getLeastSignificantBits()); 763 } 764 if (getConvoListingSize() != INVALID_VALUE_PARAMETER) { 765 appParamBuf.put((byte)CONVO_LISTING_SIZE); 766 appParamBuf.put((byte)CONVO_LISTING_SIZE_LEN); 767 appParamBuf.putShort((short)getConvoListingSize()); 768 } 769 if (getFilterPresence() != INVALID_VALUE_PARAMETER) { 770 appParamBuf.put((byte)FILTER_PRESENCE); 771 appParamBuf.put((byte)FILTER_PRESENCE_LEN); 772 appParamBuf.putShort((short)getFilterPresence()); 773 } 774 if (getFilterUidPresent() != INVALID_VALUE_PARAMETER) { 775 appParamBuf.put((byte)FILTER_UID_PRESENT); 776 appParamBuf.put((byte)FILTER_UID_PRESENT_LEN); 777 appParamBuf.putShort((short)getFilterUidPresent()); 778 } 779 if (getChatStateConvoId() != null) { 780 appParamBuf.put((byte)CHAT_STATE_CONVO_ID); 781 appParamBuf.put((byte)CHAT_STATE_CONVO_ID_LEN); 782 appParamBuf.putLong(getChatStateConvoId().getMostSignificantBits()); 783 appParamBuf.putLong(getChatStateConvoId().getLeastSignificantBits()); 784 } 785 if (getFolderVerCounter() != null) { 786 appParamBuf.put((byte)FOLDER_VER_COUNTER); 787 appParamBuf.put((byte)FOLDER_VER_COUNTER_LEN); 788 appParamBuf.put(getFolderVerCounter()); 789 } 790 if (getFilterMsgHandle() != INVALID_VALUE_PARAMETER) { 791 appParamBuf.put((byte)FILTER_MESSAGE_HANDLE); 792 appParamBuf.put((byte)FILTER_MESSAGE_HANDLE_LEN); 793 appParamBuf.putLong(getFilterMsgHandle()); 794 } 795 if (getConvoParameterMask() != INVALID_VALUE_PARAMETER) { 796 appParamBuf.put((byte) CONVO_PARAMETER_MASK); 797 appParamBuf.put((byte) CONVO_PARAMETER_MASK_LEN); 798 appParamBuf.putInt((int) getConvoParameterMask()); 799 } 800 801 // We need to reduce the length of the array to match the content 802 retBuf = Arrays.copyOfRange(appParamBuf.array(), appParamBuf.arrayOffset(), 803 appParamBuf.arrayOffset() + appParamBuf.position()); 804 return retBuf; 805 } 806 getMaxListCount()807 public int getMaxListCount() { 808 return mMaxListCount; 809 } 810 setMaxListCount(int maxListCount)811 public void setMaxListCount(int maxListCount) throws IllegalArgumentException { 812 if (maxListCount < 0 || maxListCount > 0xFFFF) 813 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); 814 this.mMaxListCount = maxListCount; 815 } 816 getStartOffset()817 public int getStartOffset() { 818 return mStartOffset; 819 } 820 setStartOffset(int startOffset)821 public void setStartOffset(int startOffset) throws IllegalArgumentException { 822 if (startOffset < 0 || startOffset > 0xFFFF) 823 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); 824 this.mStartOffset = startOffset; 825 } 826 getFilterMessageType()827 public int getFilterMessageType() { 828 return mFilterMessageType; 829 } 830 setFilterMessageType(int filterMessageType)831 public void setFilterMessageType(int filterMessageType) throws IllegalArgumentException { 832 if (filterMessageType < 0 || filterMessageType > 0x001F) 833 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x001F"); 834 this.mFilterMessageType = filterMessageType; 835 } 836 getFilterPeriodBegin()837 public long getFilterPeriodBegin() { 838 return mFilterPeriodBegin; 839 } 840 getFilterPeriodBeginString()841 public String getFilterPeriodBeginString() { 842 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 843 Date date = new Date(mFilterPeriodBegin); 844 return format.format(date); // Format to YYYYMMDDTHHMMSS local time 845 } 846 setFilterPeriodBegin(long filterPeriodBegin)847 public void setFilterPeriodBegin(long filterPeriodBegin) { 848 this.mFilterPeriodBegin = filterPeriodBegin; 849 } 850 setFilterPeriodBegin(String filterPeriodBegin)851 public void setFilterPeriodBegin(String filterPeriodBegin) throws ParseException { 852 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 853 Date date = format.parse(filterPeriodBegin); 854 this.mFilterPeriodBegin = date.getTime(); 855 } 856 getFilterLastActivityBegin()857 public long getFilterLastActivityBegin() { 858 return mFilterPeriodBegin; 859 } getFilterLastActivityBeginString()860 public String getFilterLastActivityBeginString() { 861 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 862 Date date = new Date(mFilterPeriodBegin); 863 return format.format(date); // Format to YYYYMMDDTHHMMSS local time 864 } setFilterLastActivityBegin(long filterPeriodBegin)865 public void setFilterLastActivityBegin(long filterPeriodBegin) { 866 this.mFilterPeriodBegin = filterPeriodBegin; 867 } 868 setFilterLastActivityBegin(String filterPeriodBegin)869 public void setFilterLastActivityBegin(String filterPeriodBegin)throws ParseException { 870 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 871 Date date = format.parse(filterPeriodBegin); 872 this.mFilterPeriodBegin = date.getTime(); 873 } getFilterPeriodEnd()874 public long getFilterPeriodEnd() { 875 return mFilterPeriodEnd; 876 } getFilterLastActivityEnd()877 public long getFilterLastActivityEnd() { 878 return mFilterPeriodEnd; 879 } 880 getFilterLastActivityEndString()881 public String getFilterLastActivityEndString() { 882 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 883 Date date = new Date(mFilterPeriodEnd); 884 return format.format(date); // Format to YYYYMMDDTHHMMSS local time 885 } 886 setFilterLastActivityEnd(long filterPeriodEnd)887 public void setFilterLastActivityEnd(long filterPeriodEnd) { 888 this.mFilterPeriodEnd= filterPeriodEnd; //er reuse the same 889 } 890 setFilterPeriodEnd(String filterPeriodEnd)891 public void setFilterPeriodEnd(String filterPeriodEnd) throws ParseException { 892 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 893 Date date = format.parse(filterPeriodEnd); 894 this.mFilterPeriodEnd = date.getTime(); 895 } getFilterPeriodEndString()896 public String getFilterPeriodEndString() { 897 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 898 Date date = new Date(mFilterPeriodEnd); 899 return format.format(date); // Format to YYYYMMDDTHHMMSS local time 900 } 901 setFilterPeriodEnd(long filterPeriodEnd)902 public void setFilterPeriodEnd(long filterPeriodEnd) { 903 this.mFilterPeriodEnd = filterPeriodEnd; 904 } 905 setFilterLastActivityEnd(String filterPeriodEnd)906 public void setFilterLastActivityEnd(String filterPeriodEnd) throws ParseException { 907 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 908 Date date = format.parse(filterPeriodEnd); 909 this.mFilterPeriodEnd = date.getTime(); 910 } getFilterReadStatus()911 public int getFilterReadStatus() { 912 return mFilterReadStatus; 913 } 914 setFilterReadStatus(int filterReadStatus)915 public void setFilterReadStatus(int filterReadStatus) throws IllegalArgumentException { 916 if (filterReadStatus < 0 || filterReadStatus > 0x0002) 917 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0002"); 918 this.mFilterReadStatus = filterReadStatus; 919 } 920 getFilterRecipient()921 public String getFilterRecipient() { 922 return mFilterRecipient; 923 } 924 setFilterRecipient(String filterRecipient)925 public void setFilterRecipient(String filterRecipient) { 926 this.mFilterRecipient = filterRecipient; 927 } 928 getFilterOriginator()929 public String getFilterOriginator() { 930 return mFilterOriginator; 931 } 932 setFilterOriginator(String filterOriginator)933 public void setFilterOriginator(String filterOriginator) { 934 this.mFilterOriginator = filterOriginator; 935 } 936 getFilterPriority()937 public int getFilterPriority() { 938 return mFilterPriority; 939 } 940 setFilterPriority(int filterPriority)941 public void setFilterPriority(int filterPriority) throws IllegalArgumentException { 942 if (filterPriority < 0 || filterPriority > 0x0002) 943 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0002"); 944 this.mFilterPriority = filterPriority; 945 } 946 setDatabaseIdentifier(long idHigh, long idLow)947 public void setDatabaseIdentifier(long idHigh, long idLow) { 948 this.mDatabaseIdentifierHigh = idHigh; 949 this.mDatabaseIdentifierLow = idLow; 950 } 951 getDatabaseIdentifier()952 public byte[] getDatabaseIdentifier() { 953 if(mDatabaseIdentifierLow != INVALID_VALUE_PARAMETER 954 && mDatabaseIdentifierHigh != INVALID_VALUE_PARAMETER) { 955 ByteBuffer ret = ByteBuffer.allocate(16); 956 ret.putLong(mDatabaseIdentifierHigh); 957 ret.putLong(mDatabaseIdentifierLow); 958 return ret.array(); 959 }else return null; 960 } 961 setConvoListingVerCounter(long countLow, long countHigh)962 public void setConvoListingVerCounter(long countLow, long countHigh) { 963 this.mConvoListingVerCounterHigh = countHigh; 964 this.mConvoListingVerCounterLow = countLow; 965 } 966 getConvoListingVerCounter()967 public byte[] getConvoListingVerCounter(){ 968 if(mConvoListingVerCounterHigh != INVALID_VALUE_PARAMETER && 969 mConvoListingVerCounterLow != INVALID_VALUE_PARAMETER) { 970 ByteBuffer ret = ByteBuffer.allocate(16); 971 ret.putLong(mConvoListingVerCounterHigh); 972 ret.putLong(mConvoListingVerCounterLow); 973 return ret.array(); 974 } else return null; 975 } 976 setFolderVerCounter(long countLow, long countHigh)977 public void setFolderVerCounter(long countLow, long countHigh) { 978 this.mFolderVerCounterHigh = countHigh; 979 this.mFolderVerCounterLow = countLow; 980 } 981 getFolderVerCounter()982 public byte[] getFolderVerCounter(){ 983 if(mFolderVerCounterHigh != INVALID_VALUE_PARAMETER && 984 mFolderVerCounterLow != INVALID_VALUE_PARAMETER) { 985 ByteBuffer ret = ByteBuffer.allocate(16); 986 ret.putLong(mFolderVerCounterHigh); 987 ret.putLong(mFolderVerCounterLow); 988 return ret.array(); 989 } else return null; 990 } 991 getChatStateConvoId()992 public SignedLongLong getChatStateConvoId(){ 993 return mChatStateConvoId; 994 } 995 getChatStateConvoIdByteArray()996 public byte[] getChatStateConvoIdByteArray() { 997 if(mChatStateConvoId != null) { 998 ByteBuffer ret = ByteBuffer.allocate(16); 999 ret.putLong(mChatStateConvoId.getMostSignificantBits()); 1000 ret.putLong(mChatStateConvoId.getLeastSignificantBits()); 1001 return ret.array(); 1002 } else return null; 1003 } 1004 getChatStateConvoIdString()1005 public String getChatStateConvoIdString() { 1006 String str = null; 1007 str = new String(this.getChatStateConvoIdByteArray()); 1008 return str; 1009 } 1010 setChatStateConvoId(long idHigh, long idLow)1011 public void setChatStateConvoId(long idHigh, long idLow) { 1012 mChatStateConvoId = new SignedLongLong(idLow, idHigh); 1013 } 1014 setFilterMsgHandle(String handle)1015 public void setFilterMsgHandle(String handle) { 1016 try { 1017 mFilterMsgHandle = BluetoothMapUtils.getLongFromString(handle); 1018 } catch (UnsupportedEncodingException e) { 1019 Log.w(TAG,"Error creating long from handle string", e); 1020 } 1021 } 1022 getFilterMsgHandle()1023 public long getFilterMsgHandle(){ 1024 return mFilterMsgHandle; 1025 } 1026 getFilterMsgHandleString()1027 public String getFilterMsgHandleString() { 1028 String str = null; 1029 if(mFilterMsgHandle != INVALID_VALUE_PARAMETER) { 1030 str = BluetoothMapUtils.getLongAsString(mFilterMsgHandle); 1031 } 1032 return str; 1033 } 1034 getFilterUidPresent()1035 public int getFilterUidPresent() { 1036 return mFilterUidPresent; 1037 } 1038 setFilterUidPresent(int present)1039 public void setFilterUidPresent(int present) { 1040 if (present < 0 || present > 0x00FF) 1041 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); 1042 this.mFilterUidPresent = present; 1043 } 1044 getFilterPresence()1045 public int getFilterPresence() { 1046 return mFilterPresence; 1047 } 1048 1049 1050 getFilterConvoId()1051 public SignedLongLong getFilterConvoId(){ 1052 return mFilterConvoId; 1053 } 1054 1055 /** 1056 * Get a decimal representation of the lower bits of the ConvoId - used for queries. 1057 * The upper bits are used for convo-type. 1058 * @return decimal representation of the convo ID. 1059 */ getFilterConvoIdString()1060 public String getFilterConvoIdString() { 1061 String str = null; 1062 if(mFilterConvoId != null) { 1063 str = BluetoothMapUtils.getLongAsString(mFilterConvoId.getLeastSignificantBits()); 1064 } 1065 return str; 1066 } 1067 1068 setFilterConvoId(String id)1069 public void setFilterConvoId(String id) { 1070 try { 1071 mFilterConvoId = SignedLongLong.fromString(id); 1072 } catch (UnsupportedEncodingException e) { 1073 Log.w(TAG,"Error creating long from id string", e); 1074 } 1075 } 1076 1077 setChatState(int state)1078 public void setChatState(int state) { 1079 if (state < 0 || state > 0x00FF) 1080 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); 1081 this.mChatState = state; 1082 } 1083 getChatState()1084 public int getChatState() { 1085 return mChatState; 1086 } 1087 getLastActivity()1088 public long getLastActivity(){ 1089 return this.mLastActivity; 1090 } getLastActivityString()1091 public String getLastActivityString(){ 1092 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); 1093 Date date = new Date(mLastActivity); 1094 return format.format(date); // Format to YYYYMMDDTHHMMSS local time 1095 } setLastActivity(long last)1096 public void setLastActivity(long last){ 1097 this.mLastActivity = last; 1098 } setLastActivity(String lastActivity)1099 public void setLastActivity(String lastActivity) throws ParseException { 1100 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); 1101 Date date = format.parse(lastActivity); 1102 this.mLastActivity = date.getTime(); 1103 } 1104 setPresenceStatus(String status)1105 public void setPresenceStatus(String status){ 1106 this.mPresenceStatus = status; 1107 } getPresenceStatus()1108 public String getPresenceStatus(){ 1109 return this.mPresenceStatus; 1110 } 1111 setFilterPresence(int presence)1112 public void setFilterPresence(int presence) { 1113 if (presence < 0 || presence > 0xFFFF) 1114 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); 1115 this.mFilterPresence = presence; 1116 } 1117 setPresenceAvailability(int availability)1118 public void setPresenceAvailability(int availability) { 1119 if (availability < 0 || availability > 0x00FF) 1120 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); 1121 this.mPresenceAvailability = availability; 1122 } 1123 getPresenceAvailability()1124 public int getPresenceAvailability() { 1125 return mPresenceAvailability; 1126 } 1127 getSubjectLength()1128 public int getSubjectLength() { 1129 return mSubjectLength; 1130 } getAttachment()1131 public int getAttachment() { 1132 return mAttachment; 1133 } 1134 setAttachment(int attachment)1135 public void setAttachment(int attachment) throws IllegalArgumentException { 1136 if (attachment < 0 || attachment > 0x0001) 1137 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1138 this.mAttachment = attachment; 1139 } 1140 getTransparent()1141 public int getTransparent() { 1142 return mTransparent; 1143 } 1144 setTransparent(int transparent)1145 public void setTransparent(int transparent) throws IllegalArgumentException { 1146 if (transparent < 0 || transparent > 0x0001) 1147 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1148 this.mTransparent = transparent; 1149 } 1150 getRetry()1151 public int getRetry() { 1152 return mRetry; 1153 } 1154 setRetry(int retry)1155 public void setRetry(int retry) throws IllegalArgumentException { 1156 if (retry < 0 || retry > 0x0001) 1157 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1158 this.mRetry = retry; 1159 } 1160 getNewMessage()1161 public int getNewMessage() { 1162 return mNewMessage; 1163 } 1164 setNewMessage(int newMessage)1165 public void setNewMessage(int newMessage) throws IllegalArgumentException { 1166 if (newMessage < 0 || newMessage > 0x0001) 1167 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1168 this.mNewMessage = newMessage; 1169 } 1170 getNotificationStatus()1171 public int getNotificationStatus() { 1172 return mNotificationStatus; 1173 } 1174 setNotificationStatus(int notificationStatus)1175 public void setNotificationStatus(int notificationStatus) throws IllegalArgumentException { 1176 if (notificationStatus < 0 || notificationStatus > 0x0001) 1177 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1178 this.mNotificationStatus = notificationStatus; 1179 } 1180 getNotificationFilter()1181 public long getNotificationFilter() { 1182 return mNotificationFilter; 1183 } 1184 setNotificationFilter(long notificationFilter)1185 public void setNotificationFilter(long notificationFilter) throws IllegalArgumentException { 1186 if (notificationFilter < 0 || notificationFilter > 0xFFFFFFFFL) 1187 throw new IllegalArgumentException( 1188 "Out of range, valid range is 0x0000 to 0xFFFFFFFFL"); 1189 this.mNotificationFilter = notificationFilter; 1190 } 1191 getMasInstanceId()1192 public int getMasInstanceId() { 1193 return mMasInstanceId; 1194 } 1195 setMasInstanceId(int masInstanceId)1196 public void setMasInstanceId(int masInstanceId) { 1197 if (masInstanceId < 0 || masInstanceId > 0x00FF) 1198 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); 1199 this.mMasInstanceId = masInstanceId; 1200 } 1201 getParameterMask()1202 public long getParameterMask() { 1203 return mParameterMask; 1204 } 1205 setParameterMask(long parameterMask)1206 public void setParameterMask(long parameterMask) { 1207 if (parameterMask < 0 || parameterMask > 0xFFFFFFFFL) 1208 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFFFFFF"); 1209 this.mParameterMask = parameterMask; 1210 } 1211 setConvoParameterMask(long parameterMask)1212 public void setConvoParameterMask(long parameterMask) { 1213 if (parameterMask < 0 || parameterMask > 0xFFFFFFFFL) 1214 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFFFFFF"); 1215 this.mConvoParameterMask = parameterMask; 1216 } 1217 getConvoParameterMask()1218 public long getConvoParameterMask(){ 1219 return mConvoParameterMask; 1220 } 1221 getFolderListingSize()1222 public int getFolderListingSize() { 1223 return mFolderListingSize; 1224 } 1225 setFolderListingSize(int folderListingSize)1226 public void setFolderListingSize(int folderListingSize) { 1227 if (folderListingSize < 0 || folderListingSize > 0xFFFF) 1228 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); 1229 this.mFolderListingSize = folderListingSize; 1230 } 1231 getMessageListingSize()1232 public int getMessageListingSize() { 1233 return mMessageListingSize; 1234 } 1235 setMessageListingSize(int messageListingSize)1236 public void setMessageListingSize(int messageListingSize) { 1237 if (messageListingSize < 0 || messageListingSize > 0xFFFF) 1238 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); 1239 this.mMessageListingSize = messageListingSize; 1240 } 1241 getConvoListingSize()1242 public int getConvoListingSize() { 1243 return mConvoListingSize; 1244 } 1245 setConvoListingSize(int convoListingSize)1246 public void setConvoListingSize(int convoListingSize) { 1247 if (convoListingSize < 0 || convoListingSize > 0xFFFF) 1248 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); 1249 this.mConvoListingSize = convoListingSize; 1250 } setSubjectLength(int subjectLength)1251 public void setSubjectLength(int subjectLength) { 1252 if (subjectLength < 0 || subjectLength > 0xFF) 1253 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); 1254 this.mSubjectLength = subjectLength; 1255 } 1256 getCharset()1257 public int getCharset() { 1258 return mCharset; 1259 } 1260 setCharset(int charset)1261 public void setCharset(int charset) { 1262 if (charset < 0 || charset > 0x1) 1263 throw new IllegalArgumentException("Out of range: " + charset + ", valid range is 0x0000 to 0x0001"); 1264 this.mCharset = charset; 1265 } 1266 getFractionRequest()1267 public int getFractionRequest() { 1268 return mFractionRequest; 1269 } 1270 setFractionRequest(int fractionRequest)1271 public void setFractionRequest(int fractionRequest) { 1272 if (fractionRequest < 0 || fractionRequest > 0x1) 1273 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1274 this.mFractionRequest = fractionRequest; 1275 } 1276 getFractionDeliver()1277 public int getFractionDeliver() { 1278 return mFractionDeliver; 1279 } 1280 setFractionDeliver(int fractionDeliver)1281 public void setFractionDeliver(int fractionDeliver) { 1282 if (fractionDeliver < 0 || fractionDeliver > 0x1) 1283 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1284 this.mFractionDeliver = fractionDeliver; 1285 } 1286 getStatusIndicator()1287 public int getStatusIndicator() { 1288 return mStatusIndicator; 1289 } 1290 setStatusIndicator(int statusIndicator)1291 public void setStatusIndicator(int statusIndicator) { 1292 if (statusIndicator < 0 || statusIndicator > 0x1) 1293 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1294 this.mStatusIndicator = statusIndicator; 1295 } 1296 getStatusValue()1297 public int getStatusValue() { 1298 return mStatusValue; 1299 } 1300 setStatusValue(int statusValue)1301 public void setStatusValue(int statusValue) { 1302 if (statusValue < 0 || statusValue > 0x1) 1303 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1304 this.mStatusValue = statusValue; 1305 } 1306 getMseTime()1307 public long getMseTime() { 1308 return mMseTime; 1309 } 1310 getMseTimeString()1311 public String getMseTimeString() { 1312 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); 1313 Date date = new Date(getMseTime()); 1314 return format.format(date); // Format to YYYYMMDDTHHMMSS±hhmm UTC time ± offset 1315 } 1316 setMseTime(long mseTime)1317 public void setMseTime(long mseTime) { 1318 this.mMseTime = mseTime; 1319 } 1320 setMseTime(String mseTime)1321 public void setMseTime(String mseTime) throws ParseException { 1322 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); 1323 Date date = format.parse(mseTime); 1324 this.mMseTime = date.getTime(); 1325 } 1326 1327 1328 1329 1330 } 1331