Home | History | Annotate | Download | only in map
      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      */
    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      */
    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      */
    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      */
    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      */
    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 
    808     public int getMaxListCount() {
    809         return mMaxListCount;
    810     }
    811 
    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 
    818     public int getStartOffset() {
    819         return mStartOffset;
    820     }
    821 
    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 
    828     public int getFilterMessageType() {
    829         return mFilterMessageType;
    830     }
    831 
    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 
    838     public long getFilterPeriodBegin() {
    839         return mFilterPeriodBegin;
    840     }
    841 
    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 
    848     public void setFilterPeriodBegin(long filterPeriodBegin) {
    849         this.mFilterPeriodBegin = filterPeriodBegin;
    850     }
    851 
    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 
    858     public long getFilterLastActivityBegin() {
    859         return mFilterPeriodBegin;
    860     }
    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     }
    866     public void setFilterLastActivityBegin(long filterPeriodBegin) {
    867         this.mFilterPeriodBegin = filterPeriodBegin;
    868     }
    869 
    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     }
    875     public long getFilterPeriodEnd() {
    876         return mFilterPeriodEnd;
    877     }
    878     public long getFilterLastActivityEnd() {
    879         return mFilterPeriodEnd;
    880     }
    881 
    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 
    888     public void setFilterLastActivityEnd(long filterPeriodEnd) {
    889         this.mFilterPeriodEnd= filterPeriodEnd; //er reuse the same
    890     }
    891 
    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     }
    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 
    903     public void setFilterPeriodEnd(long filterPeriodEnd) {
    904         this.mFilterPeriodEnd = filterPeriodEnd;
    905     }
    906 
    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     }
    912     public int getFilterReadStatus() {
    913         return mFilterReadStatus;
    914     }
    915 
    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 
    922     public String getFilterRecipient() {
    923         return mFilterRecipient;
    924     }
    925 
    926     public void setFilterRecipient(String filterRecipient) {
    927         this.mFilterRecipient = filterRecipient;
    928     }
    929 
    930     public String getFilterOriginator() {
    931         return mFilterOriginator;
    932     }
    933 
    934     public void setFilterOriginator(String filterOriginator) {
    935         this.mFilterOriginator = filterOriginator;
    936     }
    937 
    938     public int getFilterPriority() {
    939         return mFilterPriority;
    940     }
    941 
    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 
    948     public void setDatabaseIdentifier(long idHigh, long idLow) {
    949         this.mDatabaseIdentifierHigh = idHigh;
    950         this.mDatabaseIdentifierLow  = idLow;
    951     }
    952 
    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 
    963     public void setConvoListingVerCounter(long countLow, long countHigh) {
    964         this.mConvoListingVerCounterHigh = countHigh;
    965         this.mConvoListingVerCounterLow  = countLow;
    966     }
    967 
    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 
    978     public void setFolderVerCounter(long countLow, long countHigh) {
    979         this.mFolderVerCounterHigh = countHigh;
    980         this.mFolderVerCounterLow = countLow;
    981     }
    982 
    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 
    993     public SignedLongLong getChatStateConvoId(){
    994         return mChatStateConvoId;
    995     }
    996 
    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 
   1006     public String getChatStateConvoIdString() {
   1007         String str = null;
   1008         str = new String(this.getChatStateConvoIdByteArray());
   1009         return str;
   1010     }
   1011 
   1012     public void setChatStateConvoId(long idHigh, long idLow) {
   1013         mChatStateConvoId = new SignedLongLong(idLow, idHigh);
   1014     }
   1015 
   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 
   1024     public long getFilterMsgHandle(){
   1025         return mFilterMsgHandle;
   1026     }
   1027 
   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 
   1036     public int getFilterUidPresent() {
   1037         return mFilterUidPresent;
   1038     }
   1039 
   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 
   1046     public int getFilterPresence() {
   1047         return mFilterPresence;
   1048     }
   1049 
   1050 
   1051 
   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      */
   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 
   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 
   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 
   1085     public int getChatState() {
   1086         return mChatState;
   1087     }
   1088 
   1089     public long getLastActivity(){
   1090         return this.mLastActivity;
   1091     }
   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     }
   1097     public void setLastActivity(long last){
   1098         this.mLastActivity = last;
   1099     }
   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 
   1106     public void setPresenceStatus(String status){
   1107         this.mPresenceStatus = status;
   1108     }
   1109     public String getPresenceStatus(){
   1110         return this.mPresenceStatus;
   1111     }
   1112 
   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 
   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 
   1125     public int getPresenceAvailability() {
   1126         return mPresenceAvailability;
   1127     }
   1128 
   1129     public int getSubjectLength() {
   1130         return mSubjectLength;
   1131     }
   1132     public int getAttachment() {
   1133         return mAttachment;
   1134     }
   1135 
   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 
   1142     public int getTransparent() {
   1143         return mTransparent;
   1144     }
   1145 
   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 
   1152     public int getRetry() {
   1153         return mRetry;
   1154     }
   1155 
   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 
   1162     public int getNewMessage() {
   1163         return mNewMessage;
   1164     }
   1165 
   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 
   1172     public int getNotificationStatus() {
   1173         return mNotificationStatus;
   1174     }
   1175 
   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 
   1182     public long getNotificationFilter() {
   1183         return mNotificationFilter;
   1184     }
   1185 
   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 
   1193     public int getMasInstanceId() {
   1194         return mMasInstanceId;
   1195     }
   1196 
   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 
   1203     public long getParameterMask() {
   1204         return mParameterMask;
   1205     }
   1206 
   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 
   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 
   1219     public long getConvoParameterMask(){
   1220         return mConvoParameterMask;
   1221     }
   1222 
   1223     public int getFolderListingSize() {
   1224         return mFolderListingSize;
   1225     }
   1226 
   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 
   1233     public int getMessageListingSize() {
   1234         return mMessageListingSize;
   1235     }
   1236 
   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 
   1243     public int getConvoListingSize() {
   1244         return mConvoListingSize;
   1245     }
   1246 
   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     }
   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 
   1258     public int getCharset() {
   1259         return mCharset;
   1260     }
   1261 
   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 
   1268     public int getFractionRequest() {
   1269         return mFractionRequest;
   1270     }
   1271 
   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 
   1278     public int getFractionDeliver() {
   1279         return mFractionDeliver;
   1280     }
   1281 
   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 
   1288     public int getStatusIndicator() {
   1289         return mStatusIndicator;
   1290     }
   1291 
   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 
   1298     public int getStatusValue() {
   1299         return mStatusValue;
   1300     }
   1301 
   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 
   1308     public long getMseTime() {
   1309         return mMseTime;
   1310     }
   1311 
   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 YYYYMMDDTHHMMSShhmm UTC time  offset
   1316     }
   1317 
   1318     public void setMseTime(long mseTime) {
   1319         this.mMseTime = mseTime;
   1320     }
   1321 
   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