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 /**
     28  * This class encapsulates the appParams needed for MAP.
     29  */
     30 public class BluetoothMapAppParams {
     31 
     32     private static final String TAG = "BluetoothMapAppParams";
     33 
     34     private static final int MAX_LIST_COUNT           = 0x01;
     35     private static final int MAX_LIST_COUNT_LEN       = 0x02; //, 0x0000, 0xFFFF),
     36     private static final int START_OFFSET             = 0x02;
     37     private static final int START_OFFSET_LEN         = 0x02; //, 0x0000, 0xFFFF),
     38     private static final int FILTER_MESSAGE_TYPE      = 0x03;
     39     private static final int FILTER_MESSAGE_TYPE_LEN  = 0x01; //, 0x0000, 0x000f),
     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_READ_STATUS_LEN   = 0x01; //, 0x0000, 0x0002),
     44     private static final int FILTER_RECIPIENT         = 0x07;
     45     private static final int FILTER_ORIGINATOR        = 0x08;
     46     private static final int FILTER_PRIORITY          = 0x09;
     47     private static final int FILTER_PRIORITY_LEN      = 0x01; //, 0x0000, 0x0002),
     48     private static final int ATTACHMENT               = 0x0A;
     49     private static final int ATTACHMENT_LEN           = 0x01; //, 0x0000, 0x0001),
     50     private static final int TRANSPARENT              = 0x0B;
     51     private static final int TRANSPARENT_LEN          = 0x01; //, 0x0000, 0x0001),
     52     private static final int RETRY                    = 0x0C;
     53     private static final int RETRY_LEN                = 0x01; //, 0x0000, 0x0001),
     54     private static final int NEW_MESSAGE              = 0x0D;
     55     private static final int NEW_MESSAGE_LEN          = 0x01; //, 0x0000, 0x0001),
     56     private static final int NOTIFICATION_STATUS      = 0x0E;
     57     private static final int NOTIFICATION_STATUS_LEN  = 0x01; //, 0x0000, 0xFFFF),
     58     private static final int MAS_INSTANCE_ID          = 0x0F;
     59     private static final int MAS_INSTANCE_ID_LEN      = 0x01; //, 0x0000, 0x00FF),
     60     private static final int PARAMETER_MASK           = 0x10;
     61     private static final int PARAMETER_MASK_LEN       = 0x04; //, 0x0000, 0x0000),
     62     private static final int FOLDER_LISTING_SIZE      = 0x11;
     63     private static final int FOLDER_LISTING_SIZE_LEN  = 0x02; //, 0x0000, 0xFFFF),
     64     private static final int MESSAGE_LISTING_SIZE     = 0x12;
     65     private static final int MESSAGE_LISTING_SIZE_LEN = 0x02; //, 0x0000, 0xFFFF),
     66     private static final int SUBJECT_LENGTH           = 0x13;
     67     private static final int SUBJECT_LENGTH_LEN       = 0x01; //, 0x0000, 0x00FF),
     68     private static final int CHARSET                  = 0x14;
     69     private static final int CHARSET_LEN              = 0x01; //, 0x0000, 0x0001),
     70     private static final int FRACTION_REQUEST         = 0x15;
     71     private static final int FRACTION_REQUEST_LEN     = 0x01; //, 0x0000, 0x0001),
     72     private static final int FRACTION_DELIVER         = 0x16;
     73     private static final int FRACTION_DELIVER_LEN     = 0x01; //, 0x0000, 0x0001),
     74     private static final int STATUS_INDICATOR         = 0x17;
     75     private static final int STATUS_INDICATOR_LEN     = 0x01; //, 0x0000, 0x0001),
     76     private static final int STATUS_VALUE             = 0x18;
     77     private static final int STATUS_VALUE_LEN         = 0x01; //, 0x0000, 0x0001),
     78     private static final int MSE_TIME                 = 0x19;
     79 
     80     public static final int INVALID_VALUE_PARAMETER = -1;
     81     public static final int NOTIFICATION_STATUS_NO = 0;
     82     public static final int NOTIFICATION_STATUS_YES = 1;
     83     public static final int STATUS_INDICATOR_READ = 0;
     84     public static final int STATUS_INDICATOR_DELETED = 1;
     85     public static final int STATUS_VALUE_YES = 1;
     86     public static final int STATUS_VALUE_NO = 0;
     87     public static final int CHARSET_NATIVE = 0;
     88     public static final int CHARSET_UTF8 = 1;
     89     public static final int FRACTION_REQUEST_FIRST = 0;
     90     public static final int FRACTION_REQUEST_NEXT = 1;
     91     public static final int FRACTION_DELIVER_MORE = 0;
     92     public static final int FRACTION_DELIVER_LAST = 1;
     93 
     94 
     95     public static final int FILTER_NO_SMS_GSM  = 0x01;
     96     public static final int FILTER_NO_SMS_CDMA = 0x02;
     97     public static final int FILTER_NO_EMAIL    = 0x04;
     98     public static final int FILTER_NO_MMS      = 0x08;
     99 
    100     /* Default values for omitted application parameters */
    101     public static final long PARAMETER_MASK_ALL_ENABLED = 0xFFFF; // TODO: Update when bit 16-31 will be used.
    102 
    103     private int mMaxListCount        = INVALID_VALUE_PARAMETER;
    104     private int mStartOffset         = INVALID_VALUE_PARAMETER;
    105     private int mFilterMessageType   = INVALID_VALUE_PARAMETER;
    106     private long mFilterPeriodBegin  = INVALID_VALUE_PARAMETER;
    107     private long mFilterPeriodEnd    = INVALID_VALUE_PARAMETER;
    108     private int mFilterReadStatus    = INVALID_VALUE_PARAMETER;
    109     private String mFilterRecipient   = null;
    110     private String mFilterOriginator  = null;
    111     private int mFilterPriority      = INVALID_VALUE_PARAMETER;
    112     private int mAttachment          = INVALID_VALUE_PARAMETER;
    113     private int mTransparent         = INVALID_VALUE_PARAMETER;
    114     private int mRetry               = INVALID_VALUE_PARAMETER;
    115     private int mNewMessage          = INVALID_VALUE_PARAMETER;
    116     private int mNotificationStatus  = INVALID_VALUE_PARAMETER;
    117     private int mMasInstanceId       = INVALID_VALUE_PARAMETER;
    118     private long mParameterMask      = INVALID_VALUE_PARAMETER;
    119     private int mFolderListingSize   = INVALID_VALUE_PARAMETER;
    120     private int mMessageListingSize  = INVALID_VALUE_PARAMETER;
    121     private int mSubjectLength       = INVALID_VALUE_PARAMETER;
    122     private int mCharset             = INVALID_VALUE_PARAMETER;
    123     private int mFractionRequest     = INVALID_VALUE_PARAMETER;
    124     private int mFractionDeliver     = INVALID_VALUE_PARAMETER;
    125     private int mStatusIndicator     = INVALID_VALUE_PARAMETER;
    126     private int mStatusValue         = INVALID_VALUE_PARAMETER;
    127     private long mMseTime            = INVALID_VALUE_PARAMETER;
    128 
    129     /**
    130      * Default constructor, used to build an application parameter object to be
    131      * encoded. By default the member variables will be initialized to
    132      * {@link INVALID_VALUE_PARAMETER} for values, and empty strings for String
    133      * typed members.
    134      */
    135     public BluetoothMapAppParams() {
    136     }
    137 
    138     /**
    139      * Creates an application parameter object based on a application parameter
    140      * OBEX header. The content of the {@link appParam} byte array will be
    141      * parsed, and its content will be stored in the member variables.
    142      * {@link INVALID_VALUE_PARAMETER} can be used to determine if a value is
    143      * set or not, where strings will be empty, if {@link appParam} did not
    144      * contain the parameter.
    145      *
    146      * @param appParams
    147      *            the byte array containing the application parameters OBEX
    148      *            header
    149      * @throws IllegalArgumentException
    150      *             when a parameter does not respect the valid ranges specified
    151      *             in the MAP spec.
    152      * @throws ParseException
    153      *             if a parameter string if formated incorrectly.
    154      */
    155     public BluetoothMapAppParams(final byte[] appParams)
    156                  throws IllegalArgumentException, ParseException {
    157         ParseParams(appParams);
    158     }
    159 
    160     /**
    161      * Parse an application parameter OBEX header stored in a ByteArray.
    162      *
    163      * @param appParams
    164      *            the byte array containing the application parameters OBEX
    165      *            header
    166      * @throws IllegalArgumentException
    167      *             when a parameter does not respect the valid ranges specified
    168      *             in the MAP spec.
    169      * @throws ParseException
    170      *             if a parameter string if formated incorrectly.
    171      */
    172     private void ParseParams(final byte[] appParams) throws ParseException,
    173               IllegalArgumentException {
    174         int i = 0;
    175         int tagId, tagLength;
    176         ByteBuffer appParamBuf = ByteBuffer.wrap(appParams);
    177         appParamBuf.order(ByteOrder.BIG_ENDIAN);
    178         while (i < appParams.length) {
    179             tagId = appParams[i++] & 0xff;     // Convert to unsigned to support values above 127
    180             tagLength = appParams[i++] & 0xff; // Convert to unsigned to support values above 127
    181             switch (tagId) {
    182             case MAX_LIST_COUNT:
    183                 if (tagLength != MAX_LIST_COUNT_LEN) {
    184                     Log.w(TAG, "MAX_LIST_COUNT: Wrong length received: " + tagLength
    185                                + " expected: " + MAX_LIST_COUNT_LEN);
    186                     break;
    187                 }
    188                 setMaxListCount(appParamBuf.getShort(i) & 0xffff); // Make it unsigned
    189                 break;
    190             case START_OFFSET:
    191                 if (tagLength != START_OFFSET_LEN) {
    192                     Log.w(TAG, "START_OFFSET: Wrong length received: " + tagLength + " expected: "
    193                                + START_OFFSET_LEN);
    194                     break;
    195                 }
    196                 setStartOffset(appParamBuf.getShort(i) & 0xffff); // Make it unsigned
    197                 break;
    198             case FILTER_MESSAGE_TYPE:
    199                 if (tagLength != FILTER_MESSAGE_TYPE_LEN) {
    200                     Log.w(TAG, "FILTER_MESSAGE_TYPE: Wrong length received: " + tagLength + " expected: "
    201                             + FILTER_MESSAGE_TYPE_LEN);
    202                     break;
    203                 }
    204                     setFilterMessageType(appParams[i] & 0x0f);
    205                 break;
    206             case FILTER_PERIOD_BEGIN:
    207                 if(tagLength != 0) {
    208                     setFilterPeriodBegin(new String(appParams, i, tagLength));
    209                 }
    210                 break;
    211             case FILTER_PERIOD_END:
    212                 if(tagLength != 0) {
    213                     setFilterPeriodEnd(new String(appParams, i, tagLength));
    214                 }
    215                 break;
    216             case FILTER_READ_STATUS:
    217                 if (tagLength != FILTER_READ_STATUS_LEN) {
    218                      Log.w(TAG, "FILTER_READ_STATUS: Wrong length received: " + tagLength + " expected: "
    219                              + FILTER_READ_STATUS_LEN);
    220                      break;
    221                  }
    222                 setFilterReadStatus(appParams[i] & 0x03); // Lower two bits
    223                 break;
    224             case FILTER_RECIPIENT:
    225                 if(tagLength != 0) {
    226                     setFilterRecipient(new String(appParams, i, tagLength));
    227                 }
    228                 break;
    229             case FILTER_ORIGINATOR:
    230                 if(tagLength != 0) {
    231                     setFilterOriginator(new String(appParams, i, tagLength));
    232                 }
    233                 break;
    234             case FILTER_PRIORITY:
    235                 if (tagLength != FILTER_PRIORITY_LEN) {
    236                      Log.w(TAG, "FILTER_PRIORITY: Wrong length received: " + tagLength + " expected: "
    237                              + FILTER_PRIORITY_LEN);
    238                      break;
    239                 }
    240                 setFilterPriority(appParams[i] & 0x03); // Lower two bits
    241                 break;
    242             case ATTACHMENT:
    243                 if (tagLength != ATTACHMENT_LEN) {
    244                      Log.w(TAG, "ATTACHMENT: Wrong length received: " + tagLength + " expected: "
    245                              + ATTACHMENT_LEN);
    246                      break;
    247                 }
    248                 setAttachment(appParams[i] & 0x01); // Lower bit
    249                 break;
    250             case TRANSPARENT:
    251                 if (tagLength != TRANSPARENT_LEN) {
    252                      Log.w(TAG, "TRANSPARENT: Wrong length received: " + tagLength + " expected: "
    253                              + TRANSPARENT_LEN);
    254                      break;
    255                 }
    256                 setTransparent(appParams[i] & 0x01); // Lower bit
    257                 break;
    258             case RETRY:
    259                 if (tagLength != RETRY_LEN) {
    260                      Log.w(TAG, "RETRY: Wrong length received: " + tagLength + " expected: "
    261                              + RETRY_LEN);
    262                      break;
    263                 }
    264                 setRetry(appParams[i] & 0x01); // Lower bit
    265                 break;
    266             case NEW_MESSAGE:
    267                 if (tagLength != NEW_MESSAGE_LEN) {
    268                      Log.w(TAG, "NEW_MESSAGE: Wrong length received: " + tagLength + " expected: "
    269                              + NEW_MESSAGE_LEN);
    270                      break;
    271                 }
    272                 setNewMessage(appParams[i] & 0x01); // Lower bit
    273                 break;
    274             case NOTIFICATION_STATUS:
    275                 if (tagLength != NOTIFICATION_STATUS_LEN) {
    276                      Log.w(TAG, "NOTIFICATION_STATUS: Wrong length received: " + tagLength + " expected: "
    277                              + NOTIFICATION_STATUS_LEN);
    278                      break;
    279                 }
    280                 setNotificationStatus(appParams[i] & 0x01); // Lower bit
    281                 break;
    282             case MAS_INSTANCE_ID:
    283                 if (tagLength != MAS_INSTANCE_ID_LEN) {
    284                     Log.w(TAG, "MAS_INSTANCE_ID: Wrong length received: " + tagLength + " expected: "
    285                             + MAS_INSTANCE_ID_LEN);
    286                     break;
    287                 }
    288                 setMasInstanceId(appParams[i] & 0xff);
    289                 break;
    290             case PARAMETER_MASK:
    291                 if (tagLength != PARAMETER_MASK_LEN) {
    292                     Log.w(TAG, "PARAMETER_MASK: Wrong length received: " + tagLength + " expected: "
    293                             + PARAMETER_MASK_LEN);
    294                     break;
    295                 }
    296                 setParameterMask(appParamBuf.getInt(i) & 0xffffffffL); // Make it unsigned
    297                 break;
    298             case FOLDER_LISTING_SIZE:
    299                 if (tagLength != FOLDER_LISTING_SIZE_LEN) {
    300                     Log.w(TAG, "FOLDER_LISTING_SIZE: Wrong length received: " + tagLength + " expected: "
    301                             + FOLDER_LISTING_SIZE_LEN);
    302                     break;
    303                 }
    304                 setFolderListingSize(appParamBuf.getShort(i) & 0xffff); // Make it unsigned
    305                 break;
    306             case MESSAGE_LISTING_SIZE:
    307                 if (tagLength != MESSAGE_LISTING_SIZE_LEN) {
    308                     Log.w(TAG, "MESSAGE_LISTING_SIZE: Wrong length received: " + tagLength + " expected: "
    309                             + MESSAGE_LISTING_SIZE_LEN);
    310                     break;
    311                 }
    312                 setMessageListingSize(appParamBuf.getShort(i) & 0xffff); // Make it unsigned
    313                 break;
    314             case SUBJECT_LENGTH:
    315                 if (tagLength != SUBJECT_LENGTH_LEN) {
    316                     Log.w(TAG, "SUBJECT_LENGTH: Wrong length received: " + tagLength + " expected: "
    317                             + SUBJECT_LENGTH_LEN);
    318                     break;
    319                 }
    320                 setSubjectLength(appParams[i] & 0xff);
    321                 break;
    322             case CHARSET:
    323                 if (tagLength != CHARSET_LEN) {
    324                     Log.w(TAG, "CHARSET: Wrong length received: " + tagLength + " expected: "
    325                             + CHARSET_LEN);
    326                     break;
    327                 }
    328                 setCharset(appParams[i] & 0x01); // Lower bit
    329                 break;
    330             case FRACTION_REQUEST:
    331                 if (tagLength != FRACTION_REQUEST_LEN) {
    332                     Log.w(TAG, "FRACTION_REQUEST: Wrong length received: " + tagLength + " expected: "
    333                             + FRACTION_REQUEST_LEN);
    334                     break;
    335                 }
    336                 setFractionRequest(appParams[i] & 0x01); // Lower bit
    337                 break;
    338             case FRACTION_DELIVER:
    339                 if (tagLength != FRACTION_DELIVER_LEN) {
    340                     Log.w(TAG, "FRACTION_DELIVER: Wrong length received: " + tagLength + " expected: "
    341                             + FRACTION_DELIVER_LEN);
    342                     break;
    343                 }
    344                 setFractionDeliver(appParams[i] & 0x01); // Lower bit
    345                 break;
    346             case STATUS_INDICATOR:
    347                 if (tagLength != STATUS_INDICATOR_LEN) {
    348                     Log.w(TAG, "STATUS_INDICATOR: Wrong length received: " + tagLength + " expected: "
    349                             + STATUS_INDICATOR_LEN);
    350                     break;
    351                 }
    352                 setStatusIndicator(appParams[i] & 0x01); // Lower bit
    353                 break;
    354             case STATUS_VALUE:
    355                 if (tagLength != STATUS_VALUE_LEN) {
    356                     Log.w(TAG, "STATUS_VALUER: Wrong length received: " + tagLength + " expected: "
    357                             + STATUS_VALUE_LEN);
    358                     break;
    359                 }
    360                 setStatusValue(appParams[i] & 0x01); // Lower bit
    361                 break;
    362             case MSE_TIME:
    363                 setMseTime(new String(appParams, i, tagLength));
    364                 break;
    365             default:
    366                 // Just skip unknown Tags, no need to report error
    367                 Log.w(TAG, "Unknown TagId received ( 0x" + Integer.toString(tagId, 16)
    368                            + "), skipping...");
    369                 break;
    370             }
    371             i += tagLength; // Offset to next TagId
    372         }
    373     }
    374 
    375     /**
    376      * Get the approximate length needed to store the appParameters in a byte
    377      * array.
    378      *
    379      * @return the length in bytes
    380      * @throws UnsupportedEncodingException
    381      *             if the platform does not support UTF-8 encoding.
    382      */
    383     private int getParamMaxLength() throws UnsupportedEncodingException {
    384         int length = 0;
    385         length += 25 * 2; // tagId + tagLength
    386         length += 27; // fixed sizes
    387         length += getFilterPeriodBegin() == INVALID_VALUE_PARAMETER ? 0 : 15;
    388         length += getFilterPeriodEnd() == INVALID_VALUE_PARAMETER ? 0 : 15;
    389         if (getFilterRecipient() != null)
    390             length += getFilterRecipient().getBytes("UTF-8").length;
    391         if (getFilterOriginator() != null)
    392             length += getFilterOriginator().getBytes("UTF-8").length;
    393         length += getMseTime() == INVALID_VALUE_PARAMETER ? 0 : 20;
    394         return length;
    395     }
    396 
    397     /**
    398      * Encode the application parameter object to a byte array.
    399      *
    400      * @return a byte Array representation of the application parameter object.
    401      * @throws UnsupportedEncodingException
    402      *             if the platform does not support UTF-8 encoding.
    403      */
    404     public byte[] EncodeParams() throws UnsupportedEncodingException {
    405         ByteBuffer appParamBuf = ByteBuffer.allocate(getParamMaxLength());
    406         appParamBuf.order(ByteOrder.BIG_ENDIAN);
    407         byte[] retBuf;
    408 
    409         if (getMaxListCount() != INVALID_VALUE_PARAMETER) {
    410             appParamBuf.put((byte) MAX_LIST_COUNT);
    411             appParamBuf.put((byte) MAX_LIST_COUNT_LEN);
    412             appParamBuf.putShort((short) getMaxListCount());
    413         }
    414         if (getStartOffset() != INVALID_VALUE_PARAMETER) {
    415             appParamBuf.put((byte) START_OFFSET);
    416             appParamBuf.put((byte) START_OFFSET_LEN);
    417             appParamBuf.putShort((short) getStartOffset());
    418         }
    419         if (getFilterMessageType() != INVALID_VALUE_PARAMETER) {
    420             appParamBuf.put((byte) FILTER_MESSAGE_TYPE);
    421             appParamBuf.put((byte) FILTER_MESSAGE_TYPE_LEN);
    422             appParamBuf.put((byte) getFilterMessageType());
    423         }
    424         if (getFilterPeriodBegin() != INVALID_VALUE_PARAMETER) {
    425             appParamBuf.put((byte) FILTER_PERIOD_BEGIN);
    426             appParamBuf.put((byte) getFilterPeriodBeginString().getBytes("UTF-8").length);
    427             appParamBuf.put(getFilterPeriodBeginString().getBytes("UTF-8"));
    428         }
    429         if (getFilterPeriodEnd() != INVALID_VALUE_PARAMETER) {
    430             appParamBuf.put((byte) FILTER_PERIOD_END);
    431             appParamBuf.put((byte) getFilterPeriodEndString().getBytes("UTF-8").length);
    432             appParamBuf.put(getFilterPeriodEndString().getBytes("UTF-8"));
    433         }
    434         if (getFilterReadStatus() != INVALID_VALUE_PARAMETER) {
    435             appParamBuf.put((byte) FILTER_READ_STATUS);
    436             appParamBuf.put((byte) FILTER_READ_STATUS_LEN);
    437             appParamBuf.put((byte) getFilterReadStatus());
    438         }
    439         if (getFilterRecipient() != null) {
    440             appParamBuf.put((byte) FILTER_RECIPIENT);
    441             appParamBuf.put((byte) getFilterRecipient().getBytes("UTF-8").length);
    442             appParamBuf.put(getFilterRecipient().getBytes("UTF-8"));
    443         }
    444         if (getFilterOriginator() != null) {
    445             appParamBuf.put((byte) FILTER_ORIGINATOR);
    446             appParamBuf.put((byte) getFilterOriginator().getBytes("UTF-8").length);
    447             appParamBuf.put(getFilterOriginator().getBytes("UTF-8"));
    448         }
    449         if (getFilterPriority() != INVALID_VALUE_PARAMETER) {
    450             appParamBuf.put((byte) FILTER_PRIORITY);
    451             appParamBuf.put((byte) FILTER_PRIORITY_LEN);
    452             appParamBuf.put((byte) getFilterPriority());
    453         }
    454         if (getAttachment() != INVALID_VALUE_PARAMETER) {
    455             appParamBuf.put((byte) ATTACHMENT);
    456             appParamBuf.put((byte) ATTACHMENT_LEN);
    457             appParamBuf.put((byte) getAttachment());
    458         }
    459         if (getTransparent() != INVALID_VALUE_PARAMETER) {
    460             appParamBuf.put((byte) TRANSPARENT);
    461             appParamBuf.put((byte) TRANSPARENT_LEN);
    462             appParamBuf.put((byte) getTransparent());
    463         }
    464         if (getRetry() != INVALID_VALUE_PARAMETER) {
    465             appParamBuf.put((byte) RETRY);
    466             appParamBuf.put((byte) RETRY_LEN);
    467             appParamBuf.put((byte) getRetry());
    468         }
    469         if (getNewMessage() != INVALID_VALUE_PARAMETER) {
    470             appParamBuf.put((byte) NEW_MESSAGE);
    471             appParamBuf.put((byte) NEW_MESSAGE_LEN);
    472             appParamBuf.put((byte) getNewMessage());
    473         }
    474         if (getNotificationStatus() != INVALID_VALUE_PARAMETER) {
    475             appParamBuf.put((byte) NOTIFICATION_STATUS);
    476             appParamBuf.put((byte) NOTIFICATION_STATUS_LEN);
    477             appParamBuf.putShort((short) getNotificationStatus());
    478         }
    479         if (getMasInstanceId() != INVALID_VALUE_PARAMETER) {
    480             appParamBuf.put((byte) MAS_INSTANCE_ID);
    481             appParamBuf.put((byte) MAS_INSTANCE_ID_LEN);
    482             appParamBuf.put((byte) getMasInstanceId());
    483         }
    484         if (getParameterMask() != INVALID_VALUE_PARAMETER) {
    485             appParamBuf.put((byte) PARAMETER_MASK);
    486             appParamBuf.put((byte) PARAMETER_MASK_LEN);
    487             appParamBuf.putInt((int) getParameterMask());
    488         }
    489         if (getFolderListingSize() != INVALID_VALUE_PARAMETER) {
    490             appParamBuf.put((byte) FOLDER_LISTING_SIZE);
    491             appParamBuf.put((byte) FOLDER_LISTING_SIZE_LEN);
    492             appParamBuf.putShort((short) getFolderListingSize());
    493         }
    494         if (getMessageListingSize() != INVALID_VALUE_PARAMETER) {
    495             appParamBuf.put((byte) MESSAGE_LISTING_SIZE);
    496             appParamBuf.put((byte) MESSAGE_LISTING_SIZE_LEN);
    497             appParamBuf.putShort((short) getMessageListingSize());
    498         }
    499         if (getSubjectLength() != INVALID_VALUE_PARAMETER) {
    500             appParamBuf.put((byte) SUBJECT_LENGTH);
    501             appParamBuf.put((byte) SUBJECT_LENGTH_LEN);
    502             appParamBuf.put((byte) getSubjectLength());
    503         }
    504         if (getCharset() != INVALID_VALUE_PARAMETER) {
    505             appParamBuf.put((byte) CHARSET);
    506             appParamBuf.put((byte) CHARSET_LEN);
    507             appParamBuf.put((byte) getCharset());
    508         }
    509         if (getFractionRequest() != INVALID_VALUE_PARAMETER) {
    510             appParamBuf.put((byte) FRACTION_REQUEST);
    511             appParamBuf.put((byte) FRACTION_REQUEST_LEN);
    512             appParamBuf.put((byte) getFractionRequest());
    513         }
    514         if (getFractionDeliver() != INVALID_VALUE_PARAMETER) {
    515             appParamBuf.put((byte) FRACTION_DELIVER);
    516             appParamBuf.put((byte) FRACTION_DELIVER_LEN);
    517             appParamBuf.put((byte) getFractionDeliver());
    518         }
    519         if (getStatusIndicator() != INVALID_VALUE_PARAMETER) {
    520             appParamBuf.put((byte) STATUS_INDICATOR);
    521             appParamBuf.put((byte) STATUS_INDICATOR_LEN);
    522             appParamBuf.put((byte) getStatusIndicator());
    523         }
    524         if (getStatusValue() != INVALID_VALUE_PARAMETER) {
    525             appParamBuf.put((byte) STATUS_VALUE);
    526             appParamBuf.put((byte) STATUS_VALUE_LEN);
    527             appParamBuf.put((byte) getStatusValue());
    528         }
    529         if (getMseTime() != INVALID_VALUE_PARAMETER) {
    530             appParamBuf.put((byte) MSE_TIME);
    531             appParamBuf.put((byte) getMseTimeString().getBytes("UTF-8").length);
    532             appParamBuf.put(getMseTimeString().getBytes("UTF-8"));
    533         }
    534         // We need to reduce the length of the array to match the content
    535         retBuf = Arrays.copyOfRange(appParamBuf.array(), appParamBuf.arrayOffset(),
    536                                     appParamBuf.arrayOffset() + appParamBuf.position());
    537         return retBuf;
    538     }
    539 
    540     public int getMaxListCount() {
    541         return mMaxListCount;
    542     }
    543 
    544     public void setMaxListCount(int maxListCount) throws IllegalArgumentException {
    545         if (maxListCount < 0 || maxListCount > 0xFFFF)
    546             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF");
    547         this.mMaxListCount = maxListCount;
    548     }
    549 
    550     public int getStartOffset() {
    551         return mStartOffset;
    552     }
    553 
    554     public void setStartOffset(int startOffset) throws IllegalArgumentException {
    555         if (startOffset < 0 || startOffset > 0xFFFF)
    556             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF");
    557         this.mStartOffset = startOffset;
    558     }
    559 
    560     public int getFilterMessageType() {
    561         return mFilterMessageType;
    562     }
    563 
    564     public void setFilterMessageType(int filterMessageType) throws IllegalArgumentException {
    565         if (filterMessageType < 0 || filterMessageType > 0x000F)
    566             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x000F");
    567         this.mFilterMessageType = filterMessageType;
    568     }
    569 
    570     public long getFilterPeriodBegin() {
    571         return mFilterPeriodBegin;
    572     }
    573 
    574     public String getFilterPeriodBeginString() {
    575         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
    576         Date date = new Date(mFilterPeriodBegin);
    577         return format.format(date); // Format to YYYYMMDDTHHMMSS local time
    578     }
    579 
    580     public void setFilterPeriodBegin(long filterPeriodBegin) {
    581         this.mFilterPeriodBegin = filterPeriodBegin;
    582     }
    583 
    584     public void setFilterPeriodBegin(String filterPeriodBegin) throws ParseException {
    585         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
    586         Date date = format.parse(filterPeriodBegin);
    587         this.mFilterPeriodBegin = date.getTime();
    588     }
    589 
    590     public long getFilterPeriodEnd() {
    591         return mFilterPeriodEnd;
    592     }
    593 
    594     public String getFilterPeriodEndString() {
    595         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
    596         Date date = new Date(mFilterPeriodEnd);
    597         return format.format(date); // Format to YYYYMMDDTHHMMSS local time
    598     }
    599 
    600     public void setFilterPeriodEnd(long filterPeriodEnd) {
    601         this.mFilterPeriodEnd = filterPeriodEnd;
    602     }
    603 
    604     public void setFilterPeriodEnd(String filterPeriodEnd) throws ParseException {
    605         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
    606         Date date = format.parse(filterPeriodEnd);
    607         this.mFilterPeriodEnd = date.getTime();
    608     }
    609 
    610     public int getFilterReadStatus() {
    611         return mFilterReadStatus;
    612     }
    613 
    614     public void setFilterReadStatus(int filterReadStatus) throws IllegalArgumentException {
    615         if (filterReadStatus < 0 || filterReadStatus > 0x0002)
    616             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0002");
    617         this.mFilterReadStatus = filterReadStatus;
    618     }
    619 
    620     public String getFilterRecipient() {
    621         return mFilterRecipient;
    622     }
    623 
    624     public void setFilterRecipient(String filterRecipient) {
    625         this.mFilterRecipient = filterRecipient;
    626     }
    627 
    628     public String getFilterOriginator() {
    629         return mFilterOriginator;
    630     }
    631 
    632     public void setFilterOriginator(String filterOriginator) {
    633         this.mFilterOriginator = filterOriginator;
    634     }
    635 
    636     public int getFilterPriority() {
    637         return mFilterPriority;
    638     }
    639 
    640     public void setFilterPriority(int filterPriority) throws IllegalArgumentException {
    641         if (filterPriority < 0 || filterPriority > 0x0002)
    642             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0002");
    643         this.mFilterPriority = filterPriority;
    644     }
    645 
    646     public int getAttachment() {
    647         return mAttachment;
    648     }
    649 
    650     public void setAttachment(int attachment) throws IllegalArgumentException {
    651         if (attachment < 0 || attachment > 0x0001)
    652             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    653         this.mAttachment = attachment;
    654     }
    655 
    656     public int getTransparent() {
    657         return mTransparent;
    658     }
    659 
    660     public void setTransparent(int transparent) throws IllegalArgumentException {
    661         if (transparent < 0 || transparent > 0x0001)
    662             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    663         this.mTransparent = transparent;
    664     }
    665 
    666     public int getRetry() {
    667         return mRetry;
    668     }
    669 
    670     public void setRetry(int retry) throws IllegalArgumentException {
    671         if (retry < 0 || retry > 0x0001)
    672             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    673         this.mRetry = retry;
    674     }
    675 
    676     public int getNewMessage() {
    677         return mNewMessage;
    678     }
    679 
    680     public void setNewMessage(int newMessage) throws IllegalArgumentException {
    681         if (newMessage < 0 || newMessage > 0x0001)
    682             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    683         this.mNewMessage = newMessage;
    684     }
    685 
    686     public int getNotificationStatus() {
    687         return mNotificationStatus;
    688     }
    689 
    690     public void setNotificationStatus(int notificationStatus) throws IllegalArgumentException {
    691         if (notificationStatus < 0 || notificationStatus > 0x0001)
    692             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    693         this.mNotificationStatus = notificationStatus;
    694     }
    695 
    696     public int getMasInstanceId() {
    697         return mMasInstanceId;
    698     }
    699 
    700     public void setMasInstanceId(int masInstanceId) {
    701         if (masInstanceId < 0 || masInstanceId > 0x00FF)
    702             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF");
    703         this.mMasInstanceId = masInstanceId;
    704     }
    705 
    706     public long getParameterMask() {
    707         return mParameterMask;
    708     }
    709 
    710     public void setParameterMask(long parameterMask) {
    711         if (parameterMask < 0 || parameterMask > 0xFFFFFFFFL)
    712             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFFFFFF");
    713         this.mParameterMask = parameterMask;
    714     }
    715 
    716     public int getFolderListingSize() {
    717         return mFolderListingSize;
    718     }
    719 
    720     public void setFolderListingSize(int folderListingSize) {
    721         if (folderListingSize < 0 || folderListingSize > 0xFFFF)
    722             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF");
    723         this.mFolderListingSize = folderListingSize;
    724     }
    725 
    726     public int getMessageListingSize() {
    727         return mMessageListingSize;
    728     }
    729 
    730     public void setMessageListingSize(int messageListingSize) {
    731         if (messageListingSize < 0 || messageListingSize > 0xFFFF)
    732             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF");
    733         this.mMessageListingSize = messageListingSize;
    734     }
    735 
    736     public int getSubjectLength() {
    737         return mSubjectLength;
    738     }
    739 
    740     public void setSubjectLength(int subjectLength) {
    741         if (subjectLength < 0 || subjectLength > 0xFF)
    742             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF");
    743         this.mSubjectLength = subjectLength;
    744     }
    745 
    746     public int getCharset() {
    747         return mCharset;
    748     }
    749 
    750     public void setCharset(int charset) {
    751         if (charset < 0 || charset > 0x1)
    752             throw new IllegalArgumentException("Out of range: " + charset + ", valid range is 0x0000 to 0x0001");
    753         this.mCharset = charset;
    754     }
    755 
    756     public int getFractionRequest() {
    757         return mFractionRequest;
    758     }
    759 
    760     public void setFractionRequest(int fractionRequest) {
    761         if (fractionRequest < 0 || fractionRequest > 0x1)
    762             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    763         this.mFractionRequest = fractionRequest;
    764     }
    765 
    766     public int getFractionDeliver() {
    767         return mFractionDeliver;
    768     }
    769 
    770     public void setFractionDeliver(int fractionDeliver) {
    771         if (fractionDeliver < 0 || fractionDeliver > 0x1)
    772             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    773         this.mFractionDeliver = fractionDeliver;
    774     }
    775 
    776     public int getStatusIndicator() {
    777         return mStatusIndicator;
    778     }
    779 
    780     public void setStatusIndicator(int statusIndicator) {
    781         if (statusIndicator < 0 || statusIndicator > 0x1)
    782             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    783         this.mStatusIndicator = statusIndicator;
    784     }
    785 
    786     public int getStatusValue() {
    787         return mStatusValue;
    788     }
    789 
    790     public void setStatusValue(int statusValue) {
    791         if (statusValue < 0 || statusValue > 0x1)
    792             throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001");
    793         this.mStatusValue = statusValue;
    794     }
    795 
    796     public long getMseTime() {
    797         return mMseTime;
    798     }
    799 
    800     public String getMseTimeString() {
    801         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ");
    802         Date date = new Date(getMseTime());
    803         return format.format(date); // Format to YYYYMMDDTHHMMSShhmm UTC time  offset
    804     }
    805 
    806     public void setMseTime(long mseTime) {
    807         this.mMseTime = mseTime;
    808     }
    809 
    810     public void setMseTime(String mseTime) throws ParseException {
    811         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ");
    812         Date date = format.parse(mseTime);
    813         this.mMseTime = date.getTime();
    814     }
    815 }
    816