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 android.util.Log; 18 19 import com.android.bluetooth.SignedLongLong; 20 21 import java.io.UnsupportedEncodingException; 22 import java.nio.ByteBuffer; 23 import java.nio.ByteOrder; 24 import java.text.ParseException; 25 import java.text.SimpleDateFormat; 26 import java.util.Arrays; 27 import java.util.Date; 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) 224 throws ParseException, 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, 244 "START_OFFSET: Wrong length received: " + tagLength + " expected: " 245 + START_OFFSET_LEN); 246 } else { 247 setStartOffset(appParamBuf.getShort(i) & 0xffff); // Make it unsigned 248 } 249 break; 250 case FILTER_MESSAGE_TYPE: 251 if (tagLength != FILTER_MESSAGE_TYPE_LEN) { 252 Log.w(TAG, "FILTER_MESSAGE_TYPE: Wrong length received: " + tagLength 253 + " expected: " + FILTER_MESSAGE_TYPE_LEN); 254 } else { 255 setFilterMessageType(appParams[i] & 0x1f); 256 } 257 break; 258 case FILTER_PERIOD_BEGIN: 259 if (tagLength != 0) { 260 setFilterPeriodBegin(new String(appParams, i, tagLength)); 261 } else { 262 Log.w(TAG, "FILTER_PERIOD_BEGIN: Wrong length received: " + tagLength 263 + " expected to be more than 0"); 264 } 265 break; 266 case FILTER_PERIOD_END: 267 if (tagLength != 0) { 268 setFilterPeriodEnd(new String(appParams, i, tagLength)); 269 } else { 270 Log.w(TAG, "FILTER_PERIOD_END: Wrong length received: " + tagLength 271 + " expected to be more than 0"); 272 } 273 break; 274 case FILTER_READ_STATUS: 275 if (tagLength != FILTER_READ_STATUS_LEN) { 276 Log.w(TAG, "FILTER_READ_STATUS: Wrong length received: " + tagLength 277 + " expected: " + FILTER_READ_STATUS_LEN); 278 } else { 279 setFilterReadStatus(appParams[i] & 0x03); // Lower two bits 280 } 281 break; 282 case FILTER_RECIPIENT: 283 if (tagLength != 0) { 284 setFilterRecipient(new String(appParams, i, tagLength)); 285 } else { 286 Log.w(TAG, "FILTER_RECIPIENT: Wrong length received: " + tagLength 287 + " expected to be more than 0"); 288 } 289 break; 290 case FILTER_ORIGINATOR: 291 if (tagLength != 0) { 292 setFilterOriginator(new String(appParams, i, tagLength)); 293 } else { 294 Log.w(TAG, "FILTER_ORIGINATOR: Wrong length received: " + tagLength 295 + " expected to be more than 0"); 296 } 297 break; 298 case FILTER_PRIORITY: 299 if (tagLength != FILTER_PRIORITY_LEN) { 300 Log.w(TAG, "FILTER_PRIORITY: Wrong length received: " + tagLength 301 + " expected: " + FILTER_PRIORITY_LEN); 302 } else { 303 setFilterPriority(appParams[i] & 0x03); // Lower two bits 304 } 305 break; 306 case ATTACHMENT: 307 if (tagLength != ATTACHMENT_LEN) { 308 Log.w(TAG, "ATTACHMENT: Wrong length received: " + tagLength + " expected: " 309 + ATTACHMENT_LEN); 310 } else { 311 setAttachment(appParams[i] & 0x01); // Lower bit 312 } 313 break; 314 case TRANSPARENT: 315 if (tagLength != TRANSPARENT_LEN) { 316 Log.w(TAG, 317 "TRANSPARENT: Wrong length received: " + tagLength + " expected: " 318 + TRANSPARENT_LEN); 319 } else { 320 setTransparent(appParams[i] & 0x01); // Lower bit 321 } 322 break; 323 case RETRY: 324 if (tagLength != RETRY_LEN) { 325 Log.w(TAG, "RETRY: Wrong length received: " + tagLength + " expected: " 326 + RETRY_LEN); 327 } else { 328 setRetry(appParams[i] & 0x01); // Lower bit 329 } 330 break; 331 case NEW_MESSAGE: 332 if (tagLength != NEW_MESSAGE_LEN) { 333 Log.w(TAG, 334 "NEW_MESSAGE: Wrong length received: " + tagLength + " expected: " 335 + NEW_MESSAGE_LEN); 336 } else { 337 setNewMessage(appParams[i] & 0x01); // Lower bit 338 } 339 break; 340 case NOTIFICATION_STATUS: 341 if (tagLength != NOTIFICATION_STATUS_LEN) { 342 Log.w(TAG, "NOTIFICATION_STATUS: Wrong length received: " + tagLength 343 + " expected: " + NOTIFICATION_STATUS_LEN); 344 } else { 345 setNotificationStatus(appParams[i] & 0x01); // Lower bit 346 } 347 break; 348 case NOTIFICATION_FILTER: 349 if (tagLength != NOTIFICATION_FILTER_LEN) { 350 Log.w(TAG, "NOTIFICATION_FILTER: Wrong length received: " + tagLength 351 + " expected: " + NOTIFICATION_FILTER_LEN); 352 } else { 353 setNotificationFilter(appParamBuf.getInt(i) & 0xffffffffL); // 4 bytes 354 } 355 break; 356 case MAS_INSTANCE_ID: 357 if (tagLength != MAS_INSTANCE_ID_LEN) { 358 Log.w(TAG, "MAS_INSTANCE_ID: Wrong length received: " + tagLength 359 + " expected: " + MAS_INSTANCE_ID_LEN); 360 } else { 361 setMasInstanceId(appParams[i] & 0xff); 362 } 363 break; 364 case PARAMETER_MASK: 365 if (tagLength != PARAMETER_MASK_LEN) { 366 Log.w(TAG, "PARAMETER_MASK: Wrong length received: " + tagLength 367 + " expected: " + PARAMETER_MASK_LEN); 368 } else { 369 setParameterMask(appParamBuf.getInt(i) & 0xffffffffL); // Make it unsigned 370 } 371 break; 372 case FOLDER_LISTING_SIZE: 373 if (tagLength != FOLDER_LISTING_SIZE_LEN) { 374 Log.w(TAG, "FOLDER_LISTING_SIZE: Wrong length received: " + tagLength 375 + " expected: " + FOLDER_LISTING_SIZE_LEN); 376 } else { 377 setFolderListingSize(appParamBuf.getShort(i) & 0xffff); // Make it unsigned 378 } 379 break; 380 case MESSAGE_LISTING_SIZE: 381 if (tagLength != MESSAGE_LISTING_SIZE_LEN) { 382 Log.w(TAG, "MESSAGE_LISTING_SIZE: Wrong length received: " + tagLength 383 + " expected: " + MESSAGE_LISTING_SIZE_LEN); 384 } else { 385 setMessageListingSize(appParamBuf.getShort(i) & 0xffff); // Make it unsigned 386 } 387 break; 388 case SUBJECT_LENGTH: 389 if (tagLength != SUBJECT_LENGTH_LEN) { 390 Log.w(TAG, "SUBJECT_LENGTH: Wrong length received: " + tagLength 391 + " expected: " + SUBJECT_LENGTH_LEN); 392 } else { 393 setSubjectLength(appParams[i] & 0xff); 394 } 395 break; 396 case CHARSET: 397 if (tagLength != CHARSET_LEN) { 398 Log.w(TAG, "CHARSET: Wrong length received: " + tagLength + " expected: " 399 + CHARSET_LEN); 400 } else { 401 setCharset(appParams[i] & 0x01); // Lower bit 402 } 403 break; 404 case FRACTION_REQUEST: 405 if (tagLength != FRACTION_REQUEST_LEN) { 406 Log.w(TAG, "FRACTION_REQUEST: Wrong length received: " + tagLength 407 + " expected: " + FRACTION_REQUEST_LEN); 408 } else { 409 setFractionRequest(appParams[i] & 0x01); // Lower bit 410 } 411 break; 412 case FRACTION_DELIVER: 413 if (tagLength != FRACTION_DELIVER_LEN) { 414 Log.w(TAG, "FRACTION_DELIVER: Wrong length received: " + tagLength 415 + " expected: " + FRACTION_DELIVER_LEN); 416 } else { 417 setFractionDeliver(appParams[i] & 0x01); // Lower bit 418 } 419 break; 420 case STATUS_INDICATOR: 421 if (tagLength != STATUS_INDICATOR_LEN) { 422 Log.w(TAG, "STATUS_INDICATOR: Wrong length received: " + tagLength 423 + " expected: " + STATUS_INDICATOR_LEN); 424 } else { 425 setStatusIndicator(appParams[i] & 0x01); // Lower bit 426 } 427 break; 428 case STATUS_VALUE: 429 if (tagLength != STATUS_VALUE_LEN) { 430 Log.w(TAG, 431 "STATUS_VALUER: Wrong length received: " + tagLength + " expected: " 432 + STATUS_VALUE_LEN); 433 } else { 434 setStatusValue(appParams[i] & 0x01); // Lower bit 435 } 436 break; 437 case MSE_TIME: 438 setMseTime(new String(appParams, i, tagLength)); 439 break; 440 case DATABASE_INDETIFIER: 441 if ((tagLength != DATABASE_INDETIFIER_LEN)) { 442 Log.w(TAG, "DATABASE_IDENTIFIER: Wrong length received: " + tagLength 443 + " expected: " + DATABASE_INDETIFIER_LEN); 444 } else { 445 setDatabaseIdentifier(appParamBuf.getLong(i)/*MSB*/, 446 appParamBuf.getLong(i + 8)/*LSB*/); 447 } 448 break; 449 case CONVO_LIST_VER_COUNTER: 450 if ((tagLength != CONVO_LIST_VER_COUNTER_LEN)) { 451 Log.w(TAG, "CONVO_LIST_VER_COUNTER: Wrong length received: " + tagLength 452 + " expected: " + CONVO_LIST_VER_COUNTER_LEN); 453 } else { 454 setConvoListingVerCounter(appParamBuf.getLong(i)/*MSB*/, 455 appParamBuf.getLong(i + 8)/*LSB*/); 456 } 457 break; 458 case PRESENCE_AVAILABLE: 459 if ((tagLength != PRESENCE_AVAILABLE_LEN)) { 460 Log.w(TAG, "PRESENCE_AVAILABLE: Wrong length received: " + tagLength 461 + " expected: " + PRESENCE_AVAILABLE_LEN); 462 } else { 463 setPresenceAvailability(appParams[i]); 464 } 465 break; 466 case PRESENCE_TEXT: 467 if (tagLength != 0) { 468 setPresenceStatus(new String(appParams, i, tagLength)); 469 } else { 470 Log.w(TAG, "PRESENCE_STATUS: Wrong length received: " + tagLength 471 + " expected to be more than 0"); 472 } 473 break; 474 case LAST_ACTIVITY: 475 if (tagLength != 0) { 476 setLastActivity(new String(appParams, i, tagLength)); 477 } else { 478 Log.w(TAG, "LAST_ACTIVITY: Wrong length received: " + tagLength 479 + " expected to be more than 0"); 480 } 481 break; 482 case CHAT_STATE: 483 if ((tagLength != CHAT_STATE_LEN)) { 484 Log.w(TAG, "CHAT_STATE: Wrong length received: " + tagLength + " expected: " 485 + CHAT_STATE_LEN); 486 } else { 487 setChatState(appParams[i]); 488 } 489 break; 490 case FILTER_CONVO_ID: 491 if ((tagLength != 0) && (tagLength <= FILTER_CONVO_ID_LEN)) { 492 setFilterConvoId(new String(appParams, i, tagLength)); 493 } else { 494 Log.w(TAG, "FILTER_CONVO_ID: Wrong length received: " + tagLength 495 + " expected: " + FILTER_CONVO_ID_LEN); 496 } 497 break; 498 case CONVO_LISTING_SIZE: 499 if (tagLength != CONVO_LISTING_SIZE_LEN) { 500 Log.w(TAG, 501 "LISTING_SIZE: Wrong length received: " + tagLength + " expected: " 502 + CONVO_LISTING_SIZE_LEN); 503 504 } else { 505 setConvoListingSize(appParamBuf.getShort(i) & 0xffff); 506 } 507 break; 508 case FILTER_PRESENCE: 509 if ((tagLength != FILTER_PRESENCE_LEN)) { 510 Log.w(TAG, "FILTER_PRESENCE: Wrong length received: " + tagLength 511 + " expected: " + FILTER_PRESENCE_LEN); 512 } else { 513 setFilterPresence(appParams[i]); 514 } 515 break; 516 case FILTER_UID_PRESENT: 517 if ((tagLength != FILTER_UID_PRESENT_LEN)) { 518 Log.w(TAG, "FILTER_UID_PRESENT: Wrong length received: " + tagLength 519 + " expected: " + FILTER_UID_PRESENT_LEN); 520 } else { 521 setFilterUidPresent(appParams[i] & 0x1); 522 } 523 break; 524 case CHAT_STATE_CONVO_ID: 525 if ((tagLength != CHAT_STATE_CONVO_ID_LEN)) { 526 Log.w(TAG, "CHAT_STATE_CONVO_ID: Wrong length received: " + tagLength 527 + " expected: " + CHAT_STATE_CONVO_ID_LEN); 528 } else { 529 /* TODO: Is this correct convoId handling? */ 530 setChatStateConvoId(appParamBuf.getLong(i)/*MSB*/, 531 appParamBuf.getLong(i + 8)/*LSB*/); 532 Log.d(TAG, "CHAT_STATE_CONVO_ID: convo id " + "MSB=" 533 + BluetoothMapUtils.getLongAsString(appParamBuf.getLong(i)) 534 + ", LSB(+8)=" + BluetoothMapUtils.getLongAsString( 535 appParamBuf.getLong(i + 8))); 536 537 } 538 break; 539 case FOLDER_VER_COUNTER: 540 break; 541 case FILTER_MESSAGE_HANDLE: 542 if ((tagLength != 0 && tagLength <= FILTER_MESSAGE_HANDLE_LEN)) { 543 setFilterMsgHandle(new String(appParams, i, tagLength)); 544 } else { 545 Log.w(TAG, "FILTER_MESSAGE_HANDLE: Wrong length received: " + tagLength 546 + " expected: " + FILTER_MESSAGE_HANDLE_LEN); 547 } 548 549 break; 550 case CONVO_PARAMETER_MASK: 551 if (tagLength != CONVO_PARAMETER_MASK_LEN) { 552 Log.w(TAG, "CONVO_PARAMETER_MASK: Wrong length received: " + tagLength 553 + " expected: " + CONVO_PARAMETER_MASK_LEN); 554 } else { 555 setConvoParameterMask( 556 appParamBuf.getInt(i) & 0xffffffffL); // Make it unsigned 557 } 558 break; 559 default: 560 // Just skip unknown Tags, no need to report error 561 Log.w(TAG, "Unknown TagId received ( 0x" + Integer.toString(tagId, 16) 562 + "), skipping..."); 563 break; 564 } 565 i += tagLength; // Offset to next TagId 566 } 567 } 568 569 /** 570 * Get the approximate length needed to store the appParameters in a byte 571 * array. 572 * 573 * @return the length in bytes 574 * @throws UnsupportedEncodingException 575 * if the platform does not support UTF-8 encoding. 576 */ getParamMaxLength()577 private int getParamMaxLength() throws UnsupportedEncodingException { 578 int length = 0; 579 length += 38 * 2; // tagId + tagLength 580 length += 33 + 4 * 16; // fixed sizes TODO: Update when spec is ready 581 length += getFilterPeriodBegin() == INVALID_VALUE_PARAMETER ? 0 : 20; 582 length += getFilterPeriodEnd() == INVALID_VALUE_PARAMETER ? 0 : 20; 583 if (getFilterRecipient() != null) { 584 length += getFilterRecipient().getBytes("UTF-8").length; 585 } 586 if (getFilterOriginator() != null) { 587 length += getFilterOriginator().getBytes("UTF-8").length; 588 } 589 length += getMseTime() == INVALID_VALUE_PARAMETER ? 0 : 20; 590 if (getPresenceStatus() != null) { 591 length += getPresenceStatus().getBytes("UTF-8").length; 592 } 593 length += (getLastActivity() == INVALID_VALUE_PARAMETER) ? 0 : 20; 594 return length; 595 } 596 597 /** 598 * Encode the application parameter object to a byte array. 599 * 600 * @return a byte Array representation of the application parameter object. 601 * @throws UnsupportedEncodingException 602 * if the platform does not support UTF-8 encoding. 603 */ encodeParams()604 public byte[] encodeParams() throws UnsupportedEncodingException { 605 ByteBuffer appParamBuf = ByteBuffer.allocate(getParamMaxLength()); 606 appParamBuf.order(ByteOrder.BIG_ENDIAN); 607 byte[] retBuf; 608 609 if (getMaxListCount() != INVALID_VALUE_PARAMETER) { 610 appParamBuf.put((byte) MAX_LIST_COUNT); 611 appParamBuf.put((byte) MAX_LIST_COUNT_LEN); 612 appParamBuf.putShort((short) getMaxListCount()); 613 } 614 if (getStartOffset() != INVALID_VALUE_PARAMETER) { 615 appParamBuf.put((byte) START_OFFSET); 616 appParamBuf.put((byte) START_OFFSET_LEN); 617 appParamBuf.putShort((short) getStartOffset()); 618 } 619 if (getFilterMessageType() != INVALID_VALUE_PARAMETER) { 620 appParamBuf.put((byte) FILTER_MESSAGE_TYPE); 621 appParamBuf.put((byte) FILTER_MESSAGE_TYPE_LEN); 622 appParamBuf.put((byte) getFilterMessageType()); 623 } 624 if (getFilterPeriodBegin() != INVALID_VALUE_PARAMETER) { 625 appParamBuf.put((byte) FILTER_PERIOD_BEGIN); 626 appParamBuf.put((byte) getFilterPeriodBeginString().getBytes("UTF-8").length); 627 appParamBuf.put(getFilterPeriodBeginString().getBytes("UTF-8")); 628 } 629 if (getFilterPeriodEnd() != INVALID_VALUE_PARAMETER) { 630 appParamBuf.put((byte) FILTER_PERIOD_END); 631 appParamBuf.put((byte) getFilterPeriodEndString().getBytes("UTF-8").length); 632 appParamBuf.put(getFilterPeriodEndString().getBytes("UTF-8")); 633 } 634 if (getFilterReadStatus() != INVALID_VALUE_PARAMETER) { 635 appParamBuf.put((byte) FILTER_READ_STATUS); 636 appParamBuf.put((byte) FILTER_READ_STATUS_LEN); 637 appParamBuf.put((byte) getFilterReadStatus()); 638 } 639 if (getFilterRecipient() != null) { 640 appParamBuf.put((byte) FILTER_RECIPIENT); 641 appParamBuf.put((byte) getFilterRecipient().getBytes("UTF-8").length); 642 appParamBuf.put(getFilterRecipient().getBytes("UTF-8")); 643 } 644 if (getFilterOriginator() != null) { 645 appParamBuf.put((byte) FILTER_ORIGINATOR); 646 appParamBuf.put((byte) getFilterOriginator().getBytes("UTF-8").length); 647 appParamBuf.put(getFilterOriginator().getBytes("UTF-8")); 648 } 649 if (getFilterPriority() != INVALID_VALUE_PARAMETER) { 650 appParamBuf.put((byte) FILTER_PRIORITY); 651 appParamBuf.put((byte) FILTER_PRIORITY_LEN); 652 appParamBuf.put((byte) getFilterPriority()); 653 } 654 if (getAttachment() != INVALID_VALUE_PARAMETER) { 655 appParamBuf.put((byte) ATTACHMENT); 656 appParamBuf.put((byte) ATTACHMENT_LEN); 657 appParamBuf.put((byte) getAttachment()); 658 } 659 if (getTransparent() != INVALID_VALUE_PARAMETER) { 660 appParamBuf.put((byte) TRANSPARENT); 661 appParamBuf.put((byte) TRANSPARENT_LEN); 662 appParamBuf.put((byte) getTransparent()); 663 } 664 if (getRetry() != INVALID_VALUE_PARAMETER) { 665 appParamBuf.put((byte) RETRY); 666 appParamBuf.put((byte) RETRY_LEN); 667 appParamBuf.put((byte) getRetry()); 668 } 669 if (getNewMessage() != INVALID_VALUE_PARAMETER) { 670 appParamBuf.put((byte) NEW_MESSAGE); 671 appParamBuf.put((byte) NEW_MESSAGE_LEN); 672 appParamBuf.put((byte) getNewMessage()); 673 } 674 if (getNotificationStatus() != INVALID_VALUE_PARAMETER) { 675 appParamBuf.put((byte) NOTIFICATION_STATUS); 676 appParamBuf.put((byte) NOTIFICATION_STATUS_LEN); 677 appParamBuf.putShort((short) getNotificationStatus()); 678 } 679 if (getNotificationFilter() != INVALID_VALUE_PARAMETER) { 680 appParamBuf.put((byte) NOTIFICATION_FILTER); 681 appParamBuf.put((byte) NOTIFICATION_FILTER_LEN); 682 appParamBuf.putInt((int) getNotificationFilter()); 683 } 684 if (getMasInstanceId() != INVALID_VALUE_PARAMETER) { 685 appParamBuf.put((byte) MAS_INSTANCE_ID); 686 appParamBuf.put((byte) MAS_INSTANCE_ID_LEN); 687 appParamBuf.put((byte) getMasInstanceId()); 688 } 689 if (getParameterMask() != INVALID_VALUE_PARAMETER) { 690 appParamBuf.put((byte) PARAMETER_MASK); 691 appParamBuf.put((byte) PARAMETER_MASK_LEN); 692 appParamBuf.putInt((int) getParameterMask()); 693 } 694 if (getFolderListingSize() != INVALID_VALUE_PARAMETER) { 695 appParamBuf.put((byte) FOLDER_LISTING_SIZE); 696 appParamBuf.put((byte) FOLDER_LISTING_SIZE_LEN); 697 appParamBuf.putShort((short) getFolderListingSize()); 698 } 699 if (getMessageListingSize() != INVALID_VALUE_PARAMETER) { 700 appParamBuf.put((byte) MESSAGE_LISTING_SIZE); 701 appParamBuf.put((byte) MESSAGE_LISTING_SIZE_LEN); 702 appParamBuf.putShort((short) getMessageListingSize()); 703 } 704 if (getSubjectLength() != INVALID_VALUE_PARAMETER) { 705 appParamBuf.put((byte) SUBJECT_LENGTH); 706 appParamBuf.put((byte) SUBJECT_LENGTH_LEN); 707 appParamBuf.put((byte) getSubjectLength()); 708 } 709 if (getCharset() != INVALID_VALUE_PARAMETER) { 710 appParamBuf.put((byte) CHARSET); 711 appParamBuf.put((byte) CHARSET_LEN); 712 appParamBuf.put((byte) getCharset()); 713 } 714 if (getFractionRequest() != INVALID_VALUE_PARAMETER) { 715 appParamBuf.put((byte) FRACTION_REQUEST); 716 appParamBuf.put((byte) FRACTION_REQUEST_LEN); 717 appParamBuf.put((byte) getFractionRequest()); 718 } 719 if (getFractionDeliver() != INVALID_VALUE_PARAMETER) { 720 appParamBuf.put((byte) FRACTION_DELIVER); 721 appParamBuf.put((byte) FRACTION_DELIVER_LEN); 722 appParamBuf.put((byte) getFractionDeliver()); 723 } 724 if (getStatusIndicator() != INVALID_VALUE_PARAMETER) { 725 appParamBuf.put((byte) STATUS_INDICATOR); 726 appParamBuf.put((byte) STATUS_INDICATOR_LEN); 727 appParamBuf.put((byte) getStatusIndicator()); 728 } 729 if (getStatusValue() != INVALID_VALUE_PARAMETER) { 730 appParamBuf.put((byte) STATUS_VALUE); 731 appParamBuf.put((byte) STATUS_VALUE_LEN); 732 appParamBuf.put((byte) getStatusValue()); 733 } 734 if (getMseTime() != INVALID_VALUE_PARAMETER) { 735 appParamBuf.put((byte) MSE_TIME); 736 appParamBuf.put((byte) getMseTimeString().getBytes("UTF-8").length); 737 appParamBuf.put(getMseTimeString().getBytes("UTF-8")); 738 } 739 // Note: New for IM 740 if (getDatabaseIdentifier() != null) { 741 appParamBuf.put((byte) DATABASE_INDETIFIER); 742 appParamBuf.put((byte) DATABASE_INDETIFIER_LEN); 743 appParamBuf.put(getDatabaseIdentifier()); 744 } 745 if (getConvoListingVerCounter() != null) { 746 appParamBuf.put((byte) CONVO_LIST_VER_COUNTER); 747 appParamBuf.put((byte) CONVO_LIST_VER_COUNTER_LEN); 748 appParamBuf.put(getConvoListingVerCounter()); 749 } 750 if (getPresenceAvailability() != INVALID_VALUE_PARAMETER) { 751 appParamBuf.put((byte) PRESENCE_AVAILABLE); 752 appParamBuf.put((byte) PRESENCE_AVAILABLE_LEN); 753 appParamBuf.putInt((int) getPresenceAvailability()); 754 } 755 if (getPresenceStatus() != null) { 756 appParamBuf.put((byte) PRESENCE_TEXT); 757 appParamBuf.put((byte) getPresenceStatus().getBytes("UTF-8").length); 758 appParamBuf.put(getPresenceStatus().getBytes()); 759 } 760 if (getLastActivity() != INVALID_VALUE_PARAMETER) { 761 appParamBuf.put((byte) LAST_ACTIVITY); 762 appParamBuf.put((byte) getLastActivityString().getBytes("UTF-8").length); 763 appParamBuf.put(getLastActivityString().getBytes()); 764 } 765 if (getChatState() != INVALID_VALUE_PARAMETER) { 766 appParamBuf.put((byte) CHAT_STATE); 767 appParamBuf.put((byte) CHAT_STATE_LEN); 768 appParamBuf.putShort((short) getChatState()); 769 } 770 if (getFilterConvoId() != null) { 771 appParamBuf.put((byte) FILTER_CONVO_ID); 772 appParamBuf.put((byte) FILTER_CONVO_ID_LEN); 773 appParamBuf.putLong(getFilterConvoId().getMostSignificantBits()); 774 appParamBuf.putLong(getFilterConvoId().getLeastSignificantBits()); 775 } 776 if (getConvoListingSize() != INVALID_VALUE_PARAMETER) { 777 appParamBuf.put((byte) CONVO_LISTING_SIZE); 778 appParamBuf.put((byte) CONVO_LISTING_SIZE_LEN); 779 appParamBuf.putShort((short) getConvoListingSize()); 780 } 781 if (getFilterPresence() != INVALID_VALUE_PARAMETER) { 782 appParamBuf.put((byte) FILTER_PRESENCE); 783 appParamBuf.put((byte) FILTER_PRESENCE_LEN); 784 appParamBuf.putShort((short) getFilterPresence()); 785 } 786 if (getFilterUidPresent() != INVALID_VALUE_PARAMETER) { 787 appParamBuf.put((byte) FILTER_UID_PRESENT); 788 appParamBuf.put((byte) FILTER_UID_PRESENT_LEN); 789 appParamBuf.putShort((short) getFilterUidPresent()); 790 } 791 if (getChatStateConvoId() != null) { 792 appParamBuf.put((byte) CHAT_STATE_CONVO_ID); 793 appParamBuf.put((byte) CHAT_STATE_CONVO_ID_LEN); 794 appParamBuf.putLong(getChatStateConvoId().getMostSignificantBits()); 795 appParamBuf.putLong(getChatStateConvoId().getLeastSignificantBits()); 796 } 797 if (getFolderVerCounter() != null) { 798 appParamBuf.put((byte) FOLDER_VER_COUNTER); 799 appParamBuf.put((byte) FOLDER_VER_COUNTER_LEN); 800 appParamBuf.put(getFolderVerCounter()); 801 } 802 if (getFilterMsgHandle() != INVALID_VALUE_PARAMETER) { 803 appParamBuf.put((byte) FILTER_MESSAGE_HANDLE); 804 appParamBuf.put((byte) FILTER_MESSAGE_HANDLE_LEN); 805 appParamBuf.putLong(getFilterMsgHandle()); 806 } 807 if (getConvoParameterMask() != INVALID_VALUE_PARAMETER) { 808 appParamBuf.put((byte) CONVO_PARAMETER_MASK); 809 appParamBuf.put((byte) CONVO_PARAMETER_MASK_LEN); 810 appParamBuf.putInt((int) getConvoParameterMask()); 811 } 812 813 // We need to reduce the length of the array to match the content 814 retBuf = Arrays.copyOfRange(appParamBuf.array(), appParamBuf.arrayOffset(), 815 appParamBuf.arrayOffset() + appParamBuf.position()); 816 return retBuf; 817 } 818 getMaxListCount()819 public int getMaxListCount() { 820 return mMaxListCount; 821 } 822 setMaxListCount(int maxListCount)823 public void setMaxListCount(int maxListCount) throws IllegalArgumentException { 824 if (maxListCount < 0 || maxListCount > 0xFFFF) { 825 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); 826 } 827 this.mMaxListCount = maxListCount; 828 } 829 getStartOffset()830 public int getStartOffset() { 831 return mStartOffset; 832 } 833 setStartOffset(int startOffset)834 public void setStartOffset(int startOffset) throws IllegalArgumentException { 835 if (startOffset < 0 || startOffset > 0xFFFF) { 836 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); 837 } 838 this.mStartOffset = startOffset; 839 } 840 getFilterMessageType()841 public int getFilterMessageType() { 842 return mFilterMessageType; 843 } 844 setFilterMessageType(int filterMessageType)845 public void setFilterMessageType(int filterMessageType) throws IllegalArgumentException { 846 if (filterMessageType < 0 || filterMessageType > 0x001F) { 847 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x001F"); 848 } 849 this.mFilterMessageType = filterMessageType; 850 } 851 getFilterPeriodBegin()852 public long getFilterPeriodBegin() { 853 return mFilterPeriodBegin; 854 } 855 getFilterPeriodBeginString()856 public String getFilterPeriodBeginString() { 857 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 858 Date date = new Date(mFilterPeriodBegin); 859 return format.format(date); // Format to YYYYMMDDTHHMMSS local time 860 } 861 setFilterPeriodBegin(long filterPeriodBegin)862 public void setFilterPeriodBegin(long filterPeriodBegin) { 863 this.mFilterPeriodBegin = filterPeriodBegin; 864 } 865 setFilterPeriodBegin(String filterPeriodBegin)866 public void setFilterPeriodBegin(String filterPeriodBegin) throws ParseException { 867 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 868 Date date = format.parse(filterPeriodBegin); 869 this.mFilterPeriodBegin = date.getTime(); 870 } 871 getFilterLastActivityBegin()872 public long getFilterLastActivityBegin() { 873 return mFilterPeriodBegin; 874 } 875 getFilterLastActivityBeginString()876 public String getFilterLastActivityBeginString() { 877 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 878 Date date = new Date(mFilterPeriodBegin); 879 return format.format(date); // Format to YYYYMMDDTHHMMSS local time 880 } 881 setFilterLastActivityBegin(long filterPeriodBegin)882 public void setFilterLastActivityBegin(long filterPeriodBegin) { 883 this.mFilterPeriodBegin = filterPeriodBegin; 884 } 885 setFilterLastActivityBegin(String filterPeriodBegin)886 public void setFilterLastActivityBegin(String filterPeriodBegin) throws ParseException { 887 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 888 Date date = format.parse(filterPeriodBegin); 889 this.mFilterPeriodBegin = date.getTime(); 890 } 891 getFilterPeriodEnd()892 public long getFilterPeriodEnd() { 893 return mFilterPeriodEnd; 894 } 895 getFilterLastActivityEnd()896 public long getFilterLastActivityEnd() { 897 return mFilterPeriodEnd; 898 } 899 getFilterLastActivityEndString()900 public String getFilterLastActivityEndString() { 901 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 902 Date date = new Date(mFilterPeriodEnd); 903 return format.format(date); // Format to YYYYMMDDTHHMMSS local time 904 } 905 setFilterLastActivityEnd(long filterPeriodEnd)906 public void setFilterLastActivityEnd(long filterPeriodEnd) { 907 this.mFilterPeriodEnd = filterPeriodEnd; //er reuse the same 908 } 909 setFilterPeriodEnd(String filterPeriodEnd)910 public void setFilterPeriodEnd(String filterPeriodEnd) throws ParseException { 911 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 912 Date date = format.parse(filterPeriodEnd); 913 this.mFilterPeriodEnd = date.getTime(); 914 } 915 getFilterPeriodEndString()916 public String getFilterPeriodEndString() { 917 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 918 Date date = new Date(mFilterPeriodEnd); 919 return format.format(date); // Format to YYYYMMDDTHHMMSS local time 920 } 921 setFilterPeriodEnd(long filterPeriodEnd)922 public void setFilterPeriodEnd(long filterPeriodEnd) { 923 this.mFilterPeriodEnd = filterPeriodEnd; 924 } 925 setFilterLastActivityEnd(String filterPeriodEnd)926 public void setFilterLastActivityEnd(String filterPeriodEnd) throws ParseException { 927 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); 928 Date date = format.parse(filterPeriodEnd); 929 this.mFilterPeriodEnd = date.getTime(); 930 } 931 getFilterReadStatus()932 public int getFilterReadStatus() { 933 return mFilterReadStatus; 934 } 935 setFilterReadStatus(int filterReadStatus)936 public void setFilterReadStatus(int filterReadStatus) throws IllegalArgumentException { 937 if (filterReadStatus < 0 || filterReadStatus > 0x0002) { 938 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0002"); 939 } 940 this.mFilterReadStatus = filterReadStatus; 941 } 942 getFilterRecipient()943 public String getFilterRecipient() { 944 return mFilterRecipient; 945 } 946 setFilterRecipient(String filterRecipient)947 public void setFilterRecipient(String filterRecipient) { 948 this.mFilterRecipient = filterRecipient; 949 } 950 getFilterOriginator()951 public String getFilterOriginator() { 952 return mFilterOriginator; 953 } 954 setFilterOriginator(String filterOriginator)955 public void setFilterOriginator(String filterOriginator) { 956 this.mFilterOriginator = filterOriginator; 957 } 958 getFilterPriority()959 public int getFilterPriority() { 960 return mFilterPriority; 961 } 962 setFilterPriority(int filterPriority)963 public void setFilterPriority(int filterPriority) throws IllegalArgumentException { 964 if (filterPriority < 0 || filterPriority > 0x0002) { 965 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0002"); 966 } 967 this.mFilterPriority = filterPriority; 968 } 969 setDatabaseIdentifier(long idHigh, long idLow)970 public void setDatabaseIdentifier(long idHigh, long idLow) { 971 this.mDatabaseIdentifierHigh = idHigh; 972 this.mDatabaseIdentifierLow = idLow; 973 } 974 getDatabaseIdentifier()975 public byte[] getDatabaseIdentifier() { 976 if (mDatabaseIdentifierLow != INVALID_VALUE_PARAMETER 977 && mDatabaseIdentifierHigh != INVALID_VALUE_PARAMETER) { 978 ByteBuffer ret = ByteBuffer.allocate(16); 979 ret.putLong(mDatabaseIdentifierHigh); 980 ret.putLong(mDatabaseIdentifierLow); 981 return ret.array(); 982 } else { 983 return null; 984 } 985 } 986 setConvoListingVerCounter(long countLow, long countHigh)987 public void setConvoListingVerCounter(long countLow, long countHigh) { 988 this.mConvoListingVerCounterHigh = countHigh; 989 this.mConvoListingVerCounterLow = countLow; 990 } 991 getConvoListingVerCounter()992 public byte[] getConvoListingVerCounter() { 993 if (mConvoListingVerCounterHigh != INVALID_VALUE_PARAMETER 994 && mConvoListingVerCounterLow != INVALID_VALUE_PARAMETER) { 995 ByteBuffer ret = ByteBuffer.allocate(16); 996 ret.putLong(mConvoListingVerCounterHigh); 997 ret.putLong(mConvoListingVerCounterLow); 998 return ret.array(); 999 } else { 1000 return null; 1001 } 1002 } 1003 setFolderVerCounter(long countLow, long countHigh)1004 public void setFolderVerCounter(long countLow, long countHigh) { 1005 this.mFolderVerCounterHigh = countHigh; 1006 this.mFolderVerCounterLow = countLow; 1007 } 1008 getFolderVerCounter()1009 public byte[] getFolderVerCounter() { 1010 if (mFolderVerCounterHigh != INVALID_VALUE_PARAMETER 1011 && mFolderVerCounterLow != INVALID_VALUE_PARAMETER) { 1012 ByteBuffer ret = ByteBuffer.allocate(16); 1013 ret.putLong(mFolderVerCounterHigh); 1014 ret.putLong(mFolderVerCounterLow); 1015 return ret.array(); 1016 } else { 1017 return null; 1018 } 1019 } 1020 getChatStateConvoId()1021 public SignedLongLong getChatStateConvoId() { 1022 return mChatStateConvoId; 1023 } 1024 getChatStateConvoIdByteArray()1025 public byte[] getChatStateConvoIdByteArray() { 1026 if (mChatStateConvoId != null) { 1027 ByteBuffer ret = ByteBuffer.allocate(16); 1028 ret.putLong(mChatStateConvoId.getMostSignificantBits()); 1029 ret.putLong(mChatStateConvoId.getLeastSignificantBits()); 1030 return ret.array(); 1031 } else { 1032 return null; 1033 } 1034 } 1035 getChatStateConvoIdString()1036 public String getChatStateConvoIdString() { 1037 String str = null; 1038 str = new String(this.getChatStateConvoIdByteArray()); 1039 return str; 1040 } 1041 setChatStateConvoId(long idHigh, long idLow)1042 public void setChatStateConvoId(long idHigh, long idLow) { 1043 mChatStateConvoId = new SignedLongLong(idLow, idHigh); 1044 } 1045 setFilterMsgHandle(String handle)1046 public void setFilterMsgHandle(String handle) { 1047 try { 1048 mFilterMsgHandle = BluetoothMapUtils.getLongFromString(handle); 1049 } catch (UnsupportedEncodingException e) { 1050 Log.w(TAG, "Error creating long from handle string", e); 1051 } 1052 } 1053 getFilterMsgHandle()1054 public long getFilterMsgHandle() { 1055 return mFilterMsgHandle; 1056 } 1057 getFilterMsgHandleString()1058 public String getFilterMsgHandleString() { 1059 String str = null; 1060 if (mFilterMsgHandle != INVALID_VALUE_PARAMETER) { 1061 str = BluetoothMapUtils.getLongAsString(mFilterMsgHandle); 1062 } 1063 return str; 1064 } 1065 getFilterUidPresent()1066 public int getFilterUidPresent() { 1067 return mFilterUidPresent; 1068 } 1069 setFilterUidPresent(int present)1070 public void setFilterUidPresent(int present) { 1071 if (present < 0 || present > 0x00FF) { 1072 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); 1073 } 1074 this.mFilterUidPresent = present; 1075 } 1076 getFilterPresence()1077 public int getFilterPresence() { 1078 return mFilterPresence; 1079 } 1080 1081 getFilterConvoId()1082 public SignedLongLong getFilterConvoId() { 1083 return mFilterConvoId; 1084 } 1085 1086 /** 1087 * Get a decimal representation of the lower bits of the ConvoId - used for queries. 1088 * The upper bits are used for convo-type. 1089 * @return decimal representation of the convo ID. 1090 */ getFilterConvoIdString()1091 public String getFilterConvoIdString() { 1092 String str = null; 1093 if (mFilterConvoId != null) { 1094 str = BluetoothMapUtils.getLongAsString(mFilterConvoId.getLeastSignificantBits()); 1095 } 1096 return str; 1097 } 1098 1099 setFilterConvoId(String id)1100 public void setFilterConvoId(String id) { 1101 try { 1102 mFilterConvoId = SignedLongLong.fromString(id); 1103 } catch (UnsupportedEncodingException e) { 1104 Log.w(TAG, "Error creating long from id string", e); 1105 } 1106 } 1107 1108 setChatState(int state)1109 public void setChatState(int state) { 1110 if (state < 0 || state > 0x00FF) { 1111 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); 1112 } 1113 this.mChatState = state; 1114 } 1115 getChatState()1116 public int getChatState() { 1117 return mChatState; 1118 } 1119 getLastActivity()1120 public long getLastActivity() { 1121 return this.mLastActivity; 1122 } 1123 getLastActivityString()1124 public String getLastActivityString() { 1125 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); 1126 Date date = new Date(mLastActivity); 1127 return format.format(date); // Format to YYYYMMDDTHHMMSS local time 1128 } 1129 setLastActivity(long last)1130 public void setLastActivity(long last) { 1131 this.mLastActivity = last; 1132 } 1133 setLastActivity(String lastActivity)1134 public void setLastActivity(String lastActivity) throws ParseException { 1135 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); 1136 Date date = format.parse(lastActivity); 1137 this.mLastActivity = date.getTime(); 1138 } 1139 setPresenceStatus(String status)1140 public void setPresenceStatus(String status) { 1141 this.mPresenceStatus = status; 1142 } 1143 getPresenceStatus()1144 public String getPresenceStatus() { 1145 return this.mPresenceStatus; 1146 } 1147 setFilterPresence(int presence)1148 public void setFilterPresence(int presence) { 1149 if (presence < 0 || presence > 0xFFFF) { 1150 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); 1151 } 1152 this.mFilterPresence = presence; 1153 } 1154 setPresenceAvailability(int availability)1155 public void setPresenceAvailability(int availability) { 1156 if (availability < 0 || availability > 0x00FF) { 1157 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); 1158 } 1159 this.mPresenceAvailability = availability; 1160 } 1161 getPresenceAvailability()1162 public int getPresenceAvailability() { 1163 return mPresenceAvailability; 1164 } 1165 getSubjectLength()1166 public int getSubjectLength() { 1167 return mSubjectLength; 1168 } 1169 getAttachment()1170 public int getAttachment() { 1171 return mAttachment; 1172 } 1173 setAttachment(int attachment)1174 public void setAttachment(int attachment) throws IllegalArgumentException { 1175 if (attachment < 0 || attachment > 0x0001) { 1176 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1177 } 1178 this.mAttachment = attachment; 1179 } 1180 getTransparent()1181 public int getTransparent() { 1182 return mTransparent; 1183 } 1184 setTransparent(int transparent)1185 public void setTransparent(int transparent) throws IllegalArgumentException { 1186 if (transparent < 0 || transparent > 0x0001) { 1187 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1188 } 1189 this.mTransparent = transparent; 1190 } 1191 getRetry()1192 public int getRetry() { 1193 return mRetry; 1194 } 1195 setRetry(int retry)1196 public void setRetry(int retry) throws IllegalArgumentException { 1197 if (retry < 0 || retry > 0x0001) { 1198 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1199 } 1200 this.mRetry = retry; 1201 } 1202 getNewMessage()1203 public int getNewMessage() { 1204 return mNewMessage; 1205 } 1206 setNewMessage(int newMessage)1207 public void setNewMessage(int newMessage) throws IllegalArgumentException { 1208 if (newMessage < 0 || newMessage > 0x0001) { 1209 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1210 } 1211 this.mNewMessage = newMessage; 1212 } 1213 getNotificationStatus()1214 public int getNotificationStatus() { 1215 return mNotificationStatus; 1216 } 1217 setNotificationStatus(int notificationStatus)1218 public void setNotificationStatus(int notificationStatus) throws IllegalArgumentException { 1219 if (notificationStatus < 0 || notificationStatus > 0x0001) { 1220 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1221 } 1222 this.mNotificationStatus = notificationStatus; 1223 } 1224 getNotificationFilter()1225 public long getNotificationFilter() { 1226 return mNotificationFilter; 1227 } 1228 setNotificationFilter(long notificationFilter)1229 public void setNotificationFilter(long notificationFilter) throws IllegalArgumentException { 1230 if (notificationFilter < 0 || notificationFilter > 0xFFFFFFFFL) { 1231 throw new IllegalArgumentException( 1232 "Out of range, valid range is 0x0000 to 0xFFFFFFFFL"); 1233 } 1234 this.mNotificationFilter = notificationFilter; 1235 } 1236 getMasInstanceId()1237 public int getMasInstanceId() { 1238 return mMasInstanceId; 1239 } 1240 setMasInstanceId(int masInstanceId)1241 public void setMasInstanceId(int masInstanceId) { 1242 if (masInstanceId < 0 || masInstanceId > 0x00FF) { 1243 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); 1244 } 1245 this.mMasInstanceId = masInstanceId; 1246 } 1247 getParameterMask()1248 public long getParameterMask() { 1249 return mParameterMask; 1250 } 1251 setParameterMask(long parameterMask)1252 public void setParameterMask(long parameterMask) { 1253 if (parameterMask < 0 || parameterMask > 0xFFFFFFFFL) { 1254 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFFFFFF"); 1255 } 1256 this.mParameterMask = parameterMask; 1257 } 1258 setConvoParameterMask(long parameterMask)1259 public void setConvoParameterMask(long parameterMask) { 1260 if (parameterMask < 0 || parameterMask > 0xFFFFFFFFL) { 1261 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFFFFFF"); 1262 } 1263 this.mConvoParameterMask = parameterMask; 1264 } 1265 getConvoParameterMask()1266 public long getConvoParameterMask() { 1267 return mConvoParameterMask; 1268 } 1269 getFolderListingSize()1270 public int getFolderListingSize() { 1271 return mFolderListingSize; 1272 } 1273 setFolderListingSize(int folderListingSize)1274 public void setFolderListingSize(int folderListingSize) { 1275 if (folderListingSize < 0 || folderListingSize > 0xFFFF) { 1276 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); 1277 } 1278 this.mFolderListingSize = folderListingSize; 1279 } 1280 getMessageListingSize()1281 public int getMessageListingSize() { 1282 return mMessageListingSize; 1283 } 1284 setMessageListingSize(int messageListingSize)1285 public void setMessageListingSize(int messageListingSize) { 1286 if (messageListingSize < 0 || messageListingSize > 0xFFFF) { 1287 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); 1288 } 1289 this.mMessageListingSize = messageListingSize; 1290 } 1291 getConvoListingSize()1292 public int getConvoListingSize() { 1293 return mConvoListingSize; 1294 } 1295 setConvoListingSize(int convoListingSize)1296 public void setConvoListingSize(int convoListingSize) { 1297 if (convoListingSize < 0 || convoListingSize > 0xFFFF) { 1298 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); 1299 } 1300 this.mConvoListingSize = convoListingSize; 1301 } 1302 setSubjectLength(int subjectLength)1303 public void setSubjectLength(int subjectLength) { 1304 if (subjectLength < 0 || subjectLength > 0xFF) { 1305 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); 1306 } 1307 this.mSubjectLength = subjectLength; 1308 } 1309 getCharset()1310 public int getCharset() { 1311 return mCharset; 1312 } 1313 setCharset(int charset)1314 public void setCharset(int charset) { 1315 if (charset < 0 || charset > 0x1) { 1316 throw new IllegalArgumentException( 1317 "Out of range: " + charset + ", valid range is 0x0000 to 0x0001"); 1318 } 1319 this.mCharset = charset; 1320 } 1321 getFractionRequest()1322 public int getFractionRequest() { 1323 return mFractionRequest; 1324 } 1325 setFractionRequest(int fractionRequest)1326 public void setFractionRequest(int fractionRequest) { 1327 if (fractionRequest < 0 || fractionRequest > 0x1) { 1328 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1329 } 1330 this.mFractionRequest = fractionRequest; 1331 } 1332 getFractionDeliver()1333 public int getFractionDeliver() { 1334 return mFractionDeliver; 1335 } 1336 setFractionDeliver(int fractionDeliver)1337 public void setFractionDeliver(int fractionDeliver) { 1338 if (fractionDeliver < 0 || fractionDeliver > 0x1) { 1339 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1340 } 1341 this.mFractionDeliver = fractionDeliver; 1342 } 1343 getStatusIndicator()1344 public int getStatusIndicator() { 1345 return mStatusIndicator; 1346 } 1347 setStatusIndicator(int statusIndicator)1348 public void setStatusIndicator(int statusIndicator) { 1349 if (statusIndicator < 0 || statusIndicator > 0x1) { 1350 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1351 } 1352 this.mStatusIndicator = statusIndicator; 1353 } 1354 getStatusValue()1355 public int getStatusValue() { 1356 return mStatusValue; 1357 } 1358 setStatusValue(int statusValue)1359 public void setStatusValue(int statusValue) { 1360 if (statusValue < 0 || statusValue > 0x1) { 1361 throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); 1362 } 1363 this.mStatusValue = statusValue; 1364 } 1365 getMseTime()1366 public long getMseTime() { 1367 return mMseTime; 1368 } 1369 getMseTimeString()1370 public String getMseTimeString() { 1371 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); 1372 Date date = new Date(getMseTime()); 1373 return format.format(date); // Format to YYYYMMDDTHHMMSS±hhmm UTC time ± offset 1374 } 1375 setMseTime(long mseTime)1376 public void setMseTime(long mseTime) { 1377 this.mMseTime = mseTime; 1378 } 1379 setMseTime(String mseTime)1380 public void setMseTime(String mseTime) throws ParseException { 1381 SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); 1382 Date date = format.parse(mseTime); 1383 this.mMseTime = date.getTime(); 1384 } 1385 1386 1387 } 1388