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