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