• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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