/* * Copyright (C) 2013 Samsung System LSI * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.bluetooth.map; import android.util.Log; import com.android.bluetooth.SignedLongLong; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; /** * This class encapsulates the appParams needed for MAP. */ public class BluetoothMapAppParams { private static final String TAG = "BluetoothMapAppParams"; private static final int MAX_LIST_COUNT = 0x01; private static final int START_OFFSET = 0x02; private static final int FILTER_MESSAGE_TYPE = 0x03; private static final int FILTER_PERIOD_BEGIN = 0x04; private static final int FILTER_PERIOD_END = 0x05; private static final int FILTER_READ_STATUS = 0x06; private static final int FILTER_RECIPIENT = 0x07; private static final int FILTER_ORIGINATOR = 0x08; private static final int FILTER_PRIORITY = 0x09; private static final int ATTACHMENT = 0x0A; private static final int TRANSPARENT = 0x0B; private static final int RETRY = 0x0C; private static final int NEW_MESSAGE = 0x0D; private static final int NOTIFICATION_STATUS = 0x0E; private static final int MAS_INSTANCE_ID = 0x0F; private static final int PARAMETER_MASK = 0x10; private static final int FOLDER_LISTING_SIZE = 0x11; private static final int MESSAGE_LISTING_SIZE = 0x12; private static final int SUBJECT_LENGTH = 0x13; private static final int CHARSET = 0x14; private static final int FRACTION_REQUEST = 0x15; private static final int FRACTION_DELIVER = 0x16; private static final int STATUS_INDICATOR = 0x17; private static final int STATUS_VALUE = 0x18; private static final int MSE_TIME = 0x19; private static final int DATABASE_INDETIFIER = 0x1A; private static final int CONVO_LIST_VER_COUNTER = 0x1B; private static final int PRESENCE_AVAILABLE = 0x1C; private static final int PRESENCE_TEXT = 0x1D; private static final int LAST_ACTIVITY = 0x1E; private static final int CHAT_STATE = 0x21; private static final int FILTER_CONVO_ID = 0x22; private static final int CONVO_LISTING_SIZE = 0x36; private static final int FILTER_PRESENCE = 0x37; private static final int FILTER_UID_PRESENT = 0x38; private static final int CHAT_STATE_CONVO_ID = 0x39; private static final int FOLDER_VER_COUNTER = 0x23; private static final int FILTER_MESSAGE_HANDLE = 0x24; private static final int NOTIFICATION_FILTER = 0x25; private static final int CONVO_PARAMETER_MASK = 0x26; // Length defined for Application Parameters private static final int MAX_LIST_COUNT_LEN = 0x02; //, 0x0000, 0xFFFF), private static final int START_OFFSET_LEN = 0x02; //, 0x0000, 0xFFFF), private static final int FILTER_MESSAGE_TYPE_LEN = 0x01; //, 0x0000, 0x000f), private static final int FILTER_READ_STATUS_LEN = 0x01; //, 0x0000, 0x0002), private static final int FILTER_PRIORITY_LEN = 0x01; //, 0x0000, 0x0002), private static final int ATTACHMENT_LEN = 0x01; //, 0x0000, 0x0001), private static final int TRANSPARENT_LEN = 0x01; //, 0x0000, 0x0001), private static final int RETRY_LEN = 0x01; //, 0x0000, 0x0001), private static final int NEW_MESSAGE_LEN = 0x01; //, 0x0000, 0x0001), private static final int NOTIFICATION_STATUS_LEN = 0x01; //, 0x0000, 0xFFFF), private static final int MAS_INSTANCE_ID_LEN = 0x01; //, 0x0000, 0x00FF), private static final int PARAMETER_MASK_LEN = 0x04; //, 0x0000, 0x0000), private static final int FOLDER_LISTING_SIZE_LEN = 0x02; //, 0x0000, 0xFFFF), private static final int MESSAGE_LISTING_SIZE_LEN = 0x02; //, 0x0000, 0xFFFF), private static final int SUBJECT_LENGTH_LEN = 0x01; //, 0x0000, 0x00FF), private static final int CHARSET_LEN = 0x01; //, 0x0000, 0x0001), private static final int FRACTION_REQUEST_LEN = 0x01; //, 0x0000, 0x0001), private static final int FRACTION_DELIVER_LEN = 0x01; //, 0x0000, 0x0001), private static final int STATUS_INDICATOR_LEN = 0x01; //, 0x0000, 0x0001), private static final int STATUS_VALUE_LEN = 0x01; //, 0x0000, 0x0001), private static final int DATABASE_INDETIFIER_LEN = 0x10; private static final int CONVO_LIST_VER_COUNTER_LEN = 0x10; private static final int PRESENCE_AVAILABLE_LEN = 0X01; private static final int CHAT_STATE_LEN = 0x01; private static final int CHAT_STATE_CONVO_ID_LEN = 0x10; private static final int FILTER_CONVO_ID_LEN = 0x20; private static final int CONVO_LISTING_SIZE_LEN = 0x02; private static final int FILTER_PRESENCE_LEN = 0x01; private static final int FILTER_UID_PRESENT_LEN = 0x01; private static final int FOLDER_VER_COUNTER_LEN = 0x20; private static final int FILTER_MESSAGE_HANDLE_LEN = 0x08; private static final int NOTIFICATION_FILTER_LEN = 0x04; private static final int CONVO_PARAMETER_MASK_LEN = 0x04; // Default values public static final int INVALID_VALUE_PARAMETER = -1; public static final int NOTIFICATION_STATUS_NO = 0; public static final int NOTIFICATION_STATUS_YES = 1; public static final int STATUS_INDICATOR_READ = 0; public static final int STATUS_INDICATOR_DELETED = 1; public static final int STATUS_VALUE_YES = 1; public static final int STATUS_VALUE_NO = 0; public static final int CHARSET_NATIVE = 0; public static final int CHARSET_UTF8 = 1; public static final int FRACTION_REQUEST_FIRST = 0; public static final int FRACTION_REQUEST_NEXT = 1; public static final int FRACTION_DELIVER_MORE = 0; public static final int FRACTION_DELIVER_LAST = 1; public static final int FILTER_NO_SMS_GSM = 0x01; public static final int FILTER_NO_SMS_CDMA = 0x02; public static final int FILTER_NO_EMAIL = 0x04; public static final int FILTER_NO_MMS = 0x08; public static final int FILTER_NO_IM = 0x10; public static final int FILTER_MSG_TYPE_MASK = 0x1F; private int mMaxListCount = INVALID_VALUE_PARAMETER; private int mStartOffset = INVALID_VALUE_PARAMETER; private int mFilterMessageType = INVALID_VALUE_PARAMETER; // It seems like these are not implemented... private long mFilterPeriodBegin = INVALID_VALUE_PARAMETER; private long mFilterPeriodEnd = INVALID_VALUE_PARAMETER; private int mFilterReadStatus = INVALID_VALUE_PARAMETER; private String mFilterRecipient = null; private String mFilterOriginator = null; private int mFilterPriority = INVALID_VALUE_PARAMETER; private int mAttachment = INVALID_VALUE_PARAMETER; private int mTransparent = INVALID_VALUE_PARAMETER; private int mRetry = INVALID_VALUE_PARAMETER; private int mNewMessage = INVALID_VALUE_PARAMETER; private int mNotificationStatus = INVALID_VALUE_PARAMETER; private long mNotificationFilter = INVALID_VALUE_PARAMETER; private int mMasInstanceId = INVALID_VALUE_PARAMETER; private long mParameterMask = INVALID_VALUE_PARAMETER; private int mFolderListingSize = INVALID_VALUE_PARAMETER; private int mMessageListingSize = INVALID_VALUE_PARAMETER; private int mConvoListingSize = INVALID_VALUE_PARAMETER; private int mSubjectLength = INVALID_VALUE_PARAMETER; private int mCharset = INVALID_VALUE_PARAMETER; private int mFractionRequest = INVALID_VALUE_PARAMETER; private int mFractionDeliver = INVALID_VALUE_PARAMETER; private int mStatusIndicator = INVALID_VALUE_PARAMETER; private int mStatusValue = INVALID_VALUE_PARAMETER; private long mMseTime = INVALID_VALUE_PARAMETER; // TODO: Change to use SignedLongLong? private long mConvoListingVerCounterLow = INVALID_VALUE_PARAMETER; private long mConvoListingVerCounterHigh = INVALID_VALUE_PARAMETER; private long mDatabaseIdentifierLow = INVALID_VALUE_PARAMETER; private long mDatabaseIdentifierHigh = INVALID_VALUE_PARAMETER; private long mFolderVerCounterLow = INVALID_VALUE_PARAMETER; private long mFolderVerCounterHigh = INVALID_VALUE_PARAMETER; private int mPresenceAvailability = INVALID_VALUE_PARAMETER; private String mPresenceStatus = null; private long mLastActivity = INVALID_VALUE_PARAMETER; private int mChatState = INVALID_VALUE_PARAMETER; private SignedLongLong mFilterConvoId = null; private int mFilterPresence = INVALID_VALUE_PARAMETER; private int mFilterUidPresent = INVALID_VALUE_PARAMETER; private SignedLongLong mChatStateConvoId = null; private long mFilterMsgHandle = INVALID_VALUE_PARAMETER; private long mConvoParameterMask = INVALID_VALUE_PARAMETER; /** * Default constructor, used to build an application parameter object to be * encoded. By default the member variables will be initialized to * {@link INVALID_VALUE_PARAMETER} for values, and empty strings for String * typed members. */ public BluetoothMapAppParams() { } /** * Creates an application parameter object based on a application parameter * OBEX header. The content of the {@link appParam} byte array will be * parsed, and its content will be stored in the member variables. * {@link INVALID_VALUE_PARAMETER} can be used to determine if a value is * set or not, where strings will be empty, if {@link appParam} did not * contain the parameter. * * @param appParams * the byte array containing the application parameters OBEX * header * @throws IllegalArgumentException * when a parameter does not respect the valid ranges specified * in the MAP spec. * @throws ParseException * if a parameter string if formated incorrectly. */ public BluetoothMapAppParams(final byte[] appParams) throws IllegalArgumentException, ParseException { parseParams(appParams); } /** * Parse an application parameter OBEX header stored in a byte array. * * @param appParams * the byte array containing the application parameters OBEX * header * @throws IllegalArgumentException * when a parameter does not respect the valid ranges specified * in the MAP spec. * @throws ParseException * if a parameter string if formated incorrectly. */ private void parseParams(final byte[] appParams) throws ParseException, IllegalArgumentException { int i = 0; int tagId, tagLength; ByteBuffer appParamBuf = ByteBuffer.wrap(appParams); appParamBuf.order(ByteOrder.BIG_ENDIAN); while (i < appParams.length) { tagId = appParams[i++] & 0xff; // Convert to unsigned to support values above 127 tagLength = appParams[i++] & 0xff; // Convert to unsigned to support values above 127 switch (tagId) { case MAX_LIST_COUNT: if (tagLength != MAX_LIST_COUNT_LEN) { Log.w(TAG, "MAX_LIST_COUNT: Wrong length received: " + tagLength + " expected: " + MAX_LIST_COUNT_LEN); } else { setMaxListCount(appParamBuf.getShort(i) & 0xffff); // Make it unsigned } break; case START_OFFSET: if (tagLength != START_OFFSET_LEN) { Log.w(TAG, "START_OFFSET: Wrong length received: " + tagLength + " expected: " + START_OFFSET_LEN); } else { setStartOffset(appParamBuf.getShort(i) & 0xffff); // Make it unsigned } break; case FILTER_MESSAGE_TYPE: if (tagLength != FILTER_MESSAGE_TYPE_LEN) { Log.w(TAG, "FILTER_MESSAGE_TYPE: Wrong length received: " + tagLength + " expected: " + FILTER_MESSAGE_TYPE_LEN); } else { setFilterMessageType(appParams[i] & 0x1f); } break; case FILTER_PERIOD_BEGIN: if (tagLength != 0) { setFilterPeriodBegin(new String(appParams, i, tagLength)); } else { Log.w(TAG, "FILTER_PERIOD_BEGIN: Wrong length received: " + tagLength + " expected to be more than 0"); } break; case FILTER_PERIOD_END: if (tagLength != 0) { setFilterPeriodEnd(new String(appParams, i, tagLength)); } else { Log.w(TAG, "FILTER_PERIOD_END: Wrong length received: " + tagLength + " expected to be more than 0"); } break; case FILTER_READ_STATUS: if (tagLength != FILTER_READ_STATUS_LEN) { Log.w(TAG, "FILTER_READ_STATUS: Wrong length received: " + tagLength + " expected: " + FILTER_READ_STATUS_LEN); } else { setFilterReadStatus(appParams[i] & 0x03); // Lower two bits } break; case FILTER_RECIPIENT: if (tagLength != 0) { setFilterRecipient(new String(appParams, i, tagLength)); } else { Log.w(TAG, "FILTER_RECIPIENT: Wrong length received: " + tagLength + " expected to be more than 0"); } break; case FILTER_ORIGINATOR: if (tagLength != 0) { setFilterOriginator(new String(appParams, i, tagLength)); } else { Log.w(TAG, "FILTER_ORIGINATOR: Wrong length received: " + tagLength + " expected to be more than 0"); } break; case FILTER_PRIORITY: if (tagLength != FILTER_PRIORITY_LEN) { Log.w(TAG, "FILTER_PRIORITY: Wrong length received: " + tagLength + " expected: " + FILTER_PRIORITY_LEN); } else { setFilterPriority(appParams[i] & 0x03); // Lower two bits } break; case ATTACHMENT: if (tagLength != ATTACHMENT_LEN) { Log.w(TAG, "ATTACHMENT: Wrong length received: " + tagLength + " expected: " + ATTACHMENT_LEN); } else { setAttachment(appParams[i] & 0x01); // Lower bit } break; case TRANSPARENT: if (tagLength != TRANSPARENT_LEN) { Log.w(TAG, "TRANSPARENT: Wrong length received: " + tagLength + " expected: " + TRANSPARENT_LEN); } else { setTransparent(appParams[i] & 0x01); // Lower bit } break; case RETRY: if (tagLength != RETRY_LEN) { Log.w(TAG, "RETRY: Wrong length received: " + tagLength + " expected: " + RETRY_LEN); } else { setRetry(appParams[i] & 0x01); // Lower bit } break; case NEW_MESSAGE: if (tagLength != NEW_MESSAGE_LEN) { Log.w(TAG, "NEW_MESSAGE: Wrong length received: " + tagLength + " expected: " + NEW_MESSAGE_LEN); } else { setNewMessage(appParams[i] & 0x01); // Lower bit } break; case NOTIFICATION_STATUS: if (tagLength != NOTIFICATION_STATUS_LEN) { Log.w(TAG, "NOTIFICATION_STATUS: Wrong length received: " + tagLength + " expected: " + NOTIFICATION_STATUS_LEN); } else { setNotificationStatus(appParams[i] & 0x01); // Lower bit } break; case NOTIFICATION_FILTER: if (tagLength != NOTIFICATION_FILTER_LEN) { Log.w(TAG, "NOTIFICATION_FILTER: Wrong length received: " + tagLength + " expected: " + NOTIFICATION_FILTER_LEN); } else { setNotificationFilter(appParamBuf.getInt(i) & 0xffffffffL); // 4 bytes } break; case MAS_INSTANCE_ID: if (tagLength != MAS_INSTANCE_ID_LEN) { Log.w(TAG, "MAS_INSTANCE_ID: Wrong length received: " + tagLength + " expected: " + MAS_INSTANCE_ID_LEN); } else { setMasInstanceId(appParams[i] & 0xff); } break; case PARAMETER_MASK: if (tagLength != PARAMETER_MASK_LEN) { Log.w(TAG, "PARAMETER_MASK: Wrong length received: " + tagLength + " expected: " + PARAMETER_MASK_LEN); } else { setParameterMask(appParamBuf.getInt(i) & 0xffffffffL); // Make it unsigned } break; case FOLDER_LISTING_SIZE: if (tagLength != FOLDER_LISTING_SIZE_LEN) { Log.w(TAG, "FOLDER_LISTING_SIZE: Wrong length received: " + tagLength + " expected: " + FOLDER_LISTING_SIZE_LEN); } else { setFolderListingSize(appParamBuf.getShort(i) & 0xffff); // Make it unsigned } break; case MESSAGE_LISTING_SIZE: if (tagLength != MESSAGE_LISTING_SIZE_LEN) { Log.w(TAG, "MESSAGE_LISTING_SIZE: Wrong length received: " + tagLength + " expected: " + MESSAGE_LISTING_SIZE_LEN); } else { setMessageListingSize(appParamBuf.getShort(i) & 0xffff); // Make it unsigned } break; case SUBJECT_LENGTH: if (tagLength != SUBJECT_LENGTH_LEN) { Log.w(TAG, "SUBJECT_LENGTH: Wrong length received: " + tagLength + " expected: " + SUBJECT_LENGTH_LEN); } else { setSubjectLength(appParams[i] & 0xff); } break; case CHARSET: if (tagLength != CHARSET_LEN) { Log.w(TAG, "CHARSET: Wrong length received: " + tagLength + " expected: " + CHARSET_LEN); } else { setCharset(appParams[i] & 0x01); // Lower bit } break; case FRACTION_REQUEST: if (tagLength != FRACTION_REQUEST_LEN) { Log.w(TAG, "FRACTION_REQUEST: Wrong length received: " + tagLength + " expected: " + FRACTION_REQUEST_LEN); } else { setFractionRequest(appParams[i] & 0x01); // Lower bit } break; case FRACTION_DELIVER: if (tagLength != FRACTION_DELIVER_LEN) { Log.w(TAG, "FRACTION_DELIVER: Wrong length received: " + tagLength + " expected: " + FRACTION_DELIVER_LEN); } else { setFractionDeliver(appParams[i] & 0x01); // Lower bit } break; case STATUS_INDICATOR: if (tagLength != STATUS_INDICATOR_LEN) { Log.w(TAG, "STATUS_INDICATOR: Wrong length received: " + tagLength + " expected: " + STATUS_INDICATOR_LEN); } else { setStatusIndicator(appParams[i] & 0x01); // Lower bit } break; case STATUS_VALUE: if (tagLength != STATUS_VALUE_LEN) { Log.w(TAG, "STATUS_VALUER: Wrong length received: " + tagLength + " expected: " + STATUS_VALUE_LEN); } else { setStatusValue(appParams[i] & 0x01); // Lower bit } break; case MSE_TIME: setMseTime(new String(appParams, i, tagLength)); break; case DATABASE_INDETIFIER: if ((tagLength != DATABASE_INDETIFIER_LEN)) { Log.w(TAG, "DATABASE_IDENTIFIER: Wrong length received: " + tagLength + " expected: " + DATABASE_INDETIFIER_LEN); } else { setDatabaseIdentifier(appParamBuf.getLong(i)/*MSB*/, appParamBuf.getLong(i + 8)/*LSB*/); } break; case CONVO_LIST_VER_COUNTER: if ((tagLength != CONVO_LIST_VER_COUNTER_LEN)) { Log.w(TAG, "CONVO_LIST_VER_COUNTER: Wrong length received: " + tagLength + " expected: " + CONVO_LIST_VER_COUNTER_LEN); } else { setConvoListingVerCounter(appParamBuf.getLong(i)/*MSB*/, appParamBuf.getLong(i + 8)/*LSB*/); } break; case PRESENCE_AVAILABLE: if ((tagLength != PRESENCE_AVAILABLE_LEN)) { Log.w(TAG, "PRESENCE_AVAILABLE: Wrong length received: " + tagLength + " expected: " + PRESENCE_AVAILABLE_LEN); } else { setPresenceAvailability(appParams[i]); } break; case PRESENCE_TEXT: if (tagLength != 0) { setPresenceStatus(new String(appParams, i, tagLength)); } else { Log.w(TAG, "PRESENCE_STATUS: Wrong length received: " + tagLength + " expected to be more than 0"); } break; case LAST_ACTIVITY: if (tagLength != 0) { setLastActivity(new String(appParams, i, tagLength)); } else { Log.w(TAG, "LAST_ACTIVITY: Wrong length received: " + tagLength + " expected to be more than 0"); } break; case CHAT_STATE: if ((tagLength != CHAT_STATE_LEN)) { Log.w(TAG, "CHAT_STATE: Wrong length received: " + tagLength + " expected: " + CHAT_STATE_LEN); } else { setChatState(appParams[i]); } break; case FILTER_CONVO_ID: if ((tagLength != 0) && (tagLength <= FILTER_CONVO_ID_LEN)) { setFilterConvoId(new String(appParams, i, tagLength)); } else { Log.w(TAG, "FILTER_CONVO_ID: Wrong length received: " + tagLength + " expected: " + FILTER_CONVO_ID_LEN); } break; case CONVO_LISTING_SIZE: if (tagLength != CONVO_LISTING_SIZE_LEN) { Log.w(TAG, "LISTING_SIZE: Wrong length received: " + tagLength + " expected: " + CONVO_LISTING_SIZE_LEN); } else { setConvoListingSize(appParamBuf.getShort(i) & 0xffff); } break; case FILTER_PRESENCE: if ((tagLength != FILTER_PRESENCE_LEN)) { Log.w(TAG, "FILTER_PRESENCE: Wrong length received: " + tagLength + " expected: " + FILTER_PRESENCE_LEN); } else { setFilterPresence(appParams[i]); } break; case FILTER_UID_PRESENT: if ((tagLength != FILTER_UID_PRESENT_LEN)) { Log.w(TAG, "FILTER_UID_PRESENT: Wrong length received: " + tagLength + " expected: " + FILTER_UID_PRESENT_LEN); } else { setFilterUidPresent(appParams[i] & 0x1); } break; case CHAT_STATE_CONVO_ID: if ((tagLength != CHAT_STATE_CONVO_ID_LEN)) { Log.w(TAG, "CHAT_STATE_CONVO_ID: Wrong length received: " + tagLength + " expected: " + CHAT_STATE_CONVO_ID_LEN); } else { /* TODO: Is this correct convoId handling? */ setChatStateConvoId(appParamBuf.getLong(i)/*MSB*/, appParamBuf.getLong(i + 8)/*LSB*/); Log.d(TAG, "CHAT_STATE_CONVO_ID: convo id " + "MSB=" + BluetoothMapUtils.getLongAsString(appParamBuf.getLong(i)) + ", LSB(+8)=" + BluetoothMapUtils.getLongAsString( appParamBuf.getLong(i + 8))); } break; case FOLDER_VER_COUNTER: break; case FILTER_MESSAGE_HANDLE: if ((tagLength != 0 && tagLength <= FILTER_MESSAGE_HANDLE_LEN)) { setFilterMsgHandle(new String(appParams, i, tagLength)); } else { Log.w(TAG, "FILTER_MESSAGE_HANDLE: Wrong length received: " + tagLength + " expected: " + FILTER_MESSAGE_HANDLE_LEN); } break; case CONVO_PARAMETER_MASK: if (tagLength != CONVO_PARAMETER_MASK_LEN) { Log.w(TAG, "CONVO_PARAMETER_MASK: Wrong length received: " + tagLength + " expected: " + CONVO_PARAMETER_MASK_LEN); } else { setConvoParameterMask( appParamBuf.getInt(i) & 0xffffffffL); // Make it unsigned } break; default: // Just skip unknown Tags, no need to report error Log.w(TAG, "Unknown TagId received ( 0x" + Integer.toString(tagId, 16) + "), skipping..."); break; } i += tagLength; // Offset to next TagId } } /** * Get the approximate length needed to store the appParameters in a byte * array. * * @return the length in bytes * @throws UnsupportedEncodingException * if the platform does not support UTF-8 encoding. */ private int getParamMaxLength() throws UnsupportedEncodingException { int length = 0; length += 38 * 2; // tagId + tagLength length += 33 + 4 * 16; // fixed sizes TODO: Update when spec is ready length += getFilterPeriodBegin() == INVALID_VALUE_PARAMETER ? 0 : 20; length += getFilterPeriodEnd() == INVALID_VALUE_PARAMETER ? 0 : 20; if (getFilterRecipient() != null) { length += getFilterRecipient().getBytes("UTF-8").length; } if (getFilterOriginator() != null) { length += getFilterOriginator().getBytes("UTF-8").length; } length += getMseTime() == INVALID_VALUE_PARAMETER ? 0 : 20; if (getPresenceStatus() != null) { length += getPresenceStatus().getBytes("UTF-8").length; } length += (getLastActivity() == INVALID_VALUE_PARAMETER) ? 0 : 20; return length; } /** * Encode the application parameter object to a byte array. * * @return a byte Array representation of the application parameter object. * @throws UnsupportedEncodingException * if the platform does not support UTF-8 encoding. */ public byte[] encodeParams() throws UnsupportedEncodingException { ByteBuffer appParamBuf = ByteBuffer.allocate(getParamMaxLength()); appParamBuf.order(ByteOrder.BIG_ENDIAN); byte[] retBuf; if (getMaxListCount() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) MAX_LIST_COUNT); appParamBuf.put((byte) MAX_LIST_COUNT_LEN); appParamBuf.putShort((short) getMaxListCount()); } if (getStartOffset() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) START_OFFSET); appParamBuf.put((byte) START_OFFSET_LEN); appParamBuf.putShort((short) getStartOffset()); } if (getFilterMessageType() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) FILTER_MESSAGE_TYPE); appParamBuf.put((byte) FILTER_MESSAGE_TYPE_LEN); appParamBuf.put((byte) getFilterMessageType()); } if (getFilterPeriodBegin() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) FILTER_PERIOD_BEGIN); appParamBuf.put((byte) getFilterPeriodBeginString().getBytes("UTF-8").length); appParamBuf.put(getFilterPeriodBeginString().getBytes("UTF-8")); } if (getFilterPeriodEnd() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) FILTER_PERIOD_END); appParamBuf.put((byte) getFilterPeriodEndString().getBytes("UTF-8").length); appParamBuf.put(getFilterPeriodEndString().getBytes("UTF-8")); } if (getFilterReadStatus() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) FILTER_READ_STATUS); appParamBuf.put((byte) FILTER_READ_STATUS_LEN); appParamBuf.put((byte) getFilterReadStatus()); } if (getFilterRecipient() != null) { appParamBuf.put((byte) FILTER_RECIPIENT); appParamBuf.put((byte) getFilterRecipient().getBytes("UTF-8").length); appParamBuf.put(getFilterRecipient().getBytes("UTF-8")); } if (getFilterOriginator() != null) { appParamBuf.put((byte) FILTER_ORIGINATOR); appParamBuf.put((byte) getFilterOriginator().getBytes("UTF-8").length); appParamBuf.put(getFilterOriginator().getBytes("UTF-8")); } if (getFilterPriority() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) FILTER_PRIORITY); appParamBuf.put((byte) FILTER_PRIORITY_LEN); appParamBuf.put((byte) getFilterPriority()); } if (getAttachment() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) ATTACHMENT); appParamBuf.put((byte) ATTACHMENT_LEN); appParamBuf.put((byte) getAttachment()); } if (getTransparent() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) TRANSPARENT); appParamBuf.put((byte) TRANSPARENT_LEN); appParamBuf.put((byte) getTransparent()); } if (getRetry() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) RETRY); appParamBuf.put((byte) RETRY_LEN); appParamBuf.put((byte) getRetry()); } if (getNewMessage() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) NEW_MESSAGE); appParamBuf.put((byte) NEW_MESSAGE_LEN); appParamBuf.put((byte) getNewMessage()); } if (getNotificationStatus() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) NOTIFICATION_STATUS); appParamBuf.put((byte) NOTIFICATION_STATUS_LEN); appParamBuf.putShort((short) getNotificationStatus()); } if (getNotificationFilter() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) NOTIFICATION_FILTER); appParamBuf.put((byte) NOTIFICATION_FILTER_LEN); appParamBuf.putInt((int) getNotificationFilter()); } if (getMasInstanceId() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) MAS_INSTANCE_ID); appParamBuf.put((byte) MAS_INSTANCE_ID_LEN); appParamBuf.put((byte) getMasInstanceId()); } if (getParameterMask() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) PARAMETER_MASK); appParamBuf.put((byte) PARAMETER_MASK_LEN); appParamBuf.putInt((int) getParameterMask()); } if (getFolderListingSize() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) FOLDER_LISTING_SIZE); appParamBuf.put((byte) FOLDER_LISTING_SIZE_LEN); appParamBuf.putShort((short) getFolderListingSize()); } if (getMessageListingSize() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) MESSAGE_LISTING_SIZE); appParamBuf.put((byte) MESSAGE_LISTING_SIZE_LEN); appParamBuf.putShort((short) getMessageListingSize()); } if (getSubjectLength() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) SUBJECT_LENGTH); appParamBuf.put((byte) SUBJECT_LENGTH_LEN); appParamBuf.put((byte) getSubjectLength()); } if (getCharset() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) CHARSET); appParamBuf.put((byte) CHARSET_LEN); appParamBuf.put((byte) getCharset()); } if (getFractionRequest() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) FRACTION_REQUEST); appParamBuf.put((byte) FRACTION_REQUEST_LEN); appParamBuf.put((byte) getFractionRequest()); } if (getFractionDeliver() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) FRACTION_DELIVER); appParamBuf.put((byte) FRACTION_DELIVER_LEN); appParamBuf.put((byte) getFractionDeliver()); } if (getStatusIndicator() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) STATUS_INDICATOR); appParamBuf.put((byte) STATUS_INDICATOR_LEN); appParamBuf.put((byte) getStatusIndicator()); } if (getStatusValue() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) STATUS_VALUE); appParamBuf.put((byte) STATUS_VALUE_LEN); appParamBuf.put((byte) getStatusValue()); } if (getMseTime() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) MSE_TIME); appParamBuf.put((byte) getMseTimeString().getBytes("UTF-8").length); appParamBuf.put(getMseTimeString().getBytes("UTF-8")); } // Note: New for IM if (getDatabaseIdentifier() != null) { appParamBuf.put((byte) DATABASE_INDETIFIER); appParamBuf.put((byte) DATABASE_INDETIFIER_LEN); appParamBuf.put(getDatabaseIdentifier()); } if (getConvoListingVerCounter() != null) { appParamBuf.put((byte) CONVO_LIST_VER_COUNTER); appParamBuf.put((byte) CONVO_LIST_VER_COUNTER_LEN); appParamBuf.put(getConvoListingVerCounter()); } if (getPresenceAvailability() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) PRESENCE_AVAILABLE); appParamBuf.put((byte) PRESENCE_AVAILABLE_LEN); appParamBuf.putInt((int) getPresenceAvailability()); } if (getPresenceStatus() != null) { appParamBuf.put((byte) PRESENCE_TEXT); appParamBuf.put((byte) getPresenceStatus().getBytes("UTF-8").length); appParamBuf.put(getPresenceStatus().getBytes()); } if (getLastActivity() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) LAST_ACTIVITY); appParamBuf.put((byte) getLastActivityString().getBytes("UTF-8").length); appParamBuf.put(getLastActivityString().getBytes()); } if (getChatState() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) CHAT_STATE); appParamBuf.put((byte) CHAT_STATE_LEN); appParamBuf.putShort((short) getChatState()); } if (getFilterConvoId() != null) { appParamBuf.put((byte) FILTER_CONVO_ID); appParamBuf.put((byte) FILTER_CONVO_ID_LEN); appParamBuf.putLong(getFilterConvoId().getMostSignificantBits()); appParamBuf.putLong(getFilterConvoId().getLeastSignificantBits()); } if (getConvoListingSize() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) CONVO_LISTING_SIZE); appParamBuf.put((byte) CONVO_LISTING_SIZE_LEN); appParamBuf.putShort((short) getConvoListingSize()); } if (getFilterPresence() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) FILTER_PRESENCE); appParamBuf.put((byte) FILTER_PRESENCE_LEN); appParamBuf.putShort((short) getFilterPresence()); } if (getFilterUidPresent() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) FILTER_UID_PRESENT); appParamBuf.put((byte) FILTER_UID_PRESENT_LEN); appParamBuf.putShort((short) getFilterUidPresent()); } if (getChatStateConvoId() != null) { appParamBuf.put((byte) CHAT_STATE_CONVO_ID); appParamBuf.put((byte) CHAT_STATE_CONVO_ID_LEN); appParamBuf.putLong(getChatStateConvoId().getMostSignificantBits()); appParamBuf.putLong(getChatStateConvoId().getLeastSignificantBits()); } if (getFolderVerCounter() != null) { appParamBuf.put((byte) FOLDER_VER_COUNTER); appParamBuf.put((byte) FOLDER_VER_COUNTER_LEN); appParamBuf.put(getFolderVerCounter()); } if (getFilterMsgHandle() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) FILTER_MESSAGE_HANDLE); appParamBuf.put((byte) FILTER_MESSAGE_HANDLE_LEN); appParamBuf.putLong(getFilterMsgHandle()); } if (getConvoParameterMask() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) CONVO_PARAMETER_MASK); appParamBuf.put((byte) CONVO_PARAMETER_MASK_LEN); appParamBuf.putInt((int) getConvoParameterMask()); } // We need to reduce the length of the array to match the content retBuf = Arrays.copyOfRange(appParamBuf.array(), appParamBuf.arrayOffset(), appParamBuf.arrayOffset() + appParamBuf.position()); return retBuf; } public int getMaxListCount() { return mMaxListCount; } public void setMaxListCount(int maxListCount) throws IllegalArgumentException { if (maxListCount < 0 || maxListCount > 0xFFFF) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); } this.mMaxListCount = maxListCount; } public int getStartOffset() { return mStartOffset; } public void setStartOffset(int startOffset) throws IllegalArgumentException { if (startOffset < 0 || startOffset > 0xFFFF) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); } this.mStartOffset = startOffset; } public int getFilterMessageType() { return mFilterMessageType; } public void setFilterMessageType(int filterMessageType) throws IllegalArgumentException { if (filterMessageType < 0 || filterMessageType > 0x001F) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x001F"); } this.mFilterMessageType = filterMessageType; } public long getFilterPeriodBegin() { return mFilterPeriodBegin; } public String getFilterPeriodBeginString() { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); Date date = new Date(mFilterPeriodBegin); return format.format(date); // Format to YYYYMMDDTHHMMSS local time } public void setFilterPeriodBegin(long filterPeriodBegin) { this.mFilterPeriodBegin = filterPeriodBegin; } public void setFilterPeriodBegin(String filterPeriodBegin) throws ParseException { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); Date date = format.parse(filterPeriodBegin); this.mFilterPeriodBegin = date.getTime(); } public long getFilterLastActivityBegin() { return mFilterPeriodBegin; } public String getFilterLastActivityBeginString() { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); Date date = new Date(mFilterPeriodBegin); return format.format(date); // Format to YYYYMMDDTHHMMSS local time } public void setFilterLastActivityBegin(long filterPeriodBegin) { this.mFilterPeriodBegin = filterPeriodBegin; } public void setFilterLastActivityBegin(String filterPeriodBegin) throws ParseException { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); Date date = format.parse(filterPeriodBegin); this.mFilterPeriodBegin = date.getTime(); } public long getFilterPeriodEnd() { return mFilterPeriodEnd; } public long getFilterLastActivityEnd() { return mFilterPeriodEnd; } public String getFilterLastActivityEndString() { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); Date date = new Date(mFilterPeriodEnd); return format.format(date); // Format to YYYYMMDDTHHMMSS local time } public void setFilterLastActivityEnd(long filterPeriodEnd) { this.mFilterPeriodEnd = filterPeriodEnd; //er reuse the same } public void setFilterPeriodEnd(String filterPeriodEnd) throws ParseException { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); Date date = format.parse(filterPeriodEnd); this.mFilterPeriodEnd = date.getTime(); } public String getFilterPeriodEndString() { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); Date date = new Date(mFilterPeriodEnd); return format.format(date); // Format to YYYYMMDDTHHMMSS local time } public void setFilterPeriodEnd(long filterPeriodEnd) { this.mFilterPeriodEnd = filterPeriodEnd; } public void setFilterLastActivityEnd(String filterPeriodEnd) throws ParseException { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); Date date = format.parse(filterPeriodEnd); this.mFilterPeriodEnd = date.getTime(); } public int getFilterReadStatus() { return mFilterReadStatus; } public void setFilterReadStatus(int filterReadStatus) throws IllegalArgumentException { if (filterReadStatus < 0 || filterReadStatus > 0x0002) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0002"); } this.mFilterReadStatus = filterReadStatus; } public String getFilterRecipient() { return mFilterRecipient; } public void setFilterRecipient(String filterRecipient) { this.mFilterRecipient = filterRecipient; } public String getFilterOriginator() { return mFilterOriginator; } public void setFilterOriginator(String filterOriginator) { this.mFilterOriginator = filterOriginator; } public int getFilterPriority() { return mFilterPriority; } public void setFilterPriority(int filterPriority) throws IllegalArgumentException { if (filterPriority < 0 || filterPriority > 0x0002) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0002"); } this.mFilterPriority = filterPriority; } public void setDatabaseIdentifier(long idHigh, long idLow) { this.mDatabaseIdentifierHigh = idHigh; this.mDatabaseIdentifierLow = idLow; } public byte[] getDatabaseIdentifier() { if (mDatabaseIdentifierLow != INVALID_VALUE_PARAMETER && mDatabaseIdentifierHigh != INVALID_VALUE_PARAMETER) { ByteBuffer ret = ByteBuffer.allocate(16); ret.putLong(mDatabaseIdentifierHigh); ret.putLong(mDatabaseIdentifierLow); return ret.array(); } else { return null; } } public void setConvoListingVerCounter(long countLow, long countHigh) { this.mConvoListingVerCounterHigh = countHigh; this.mConvoListingVerCounterLow = countLow; } public byte[] getConvoListingVerCounter() { if (mConvoListingVerCounterHigh != INVALID_VALUE_PARAMETER && mConvoListingVerCounterLow != INVALID_VALUE_PARAMETER) { ByteBuffer ret = ByteBuffer.allocate(16); ret.putLong(mConvoListingVerCounterHigh); ret.putLong(mConvoListingVerCounterLow); return ret.array(); } else { return null; } } public void setFolderVerCounter(long countLow, long countHigh) { this.mFolderVerCounterHigh = countHigh; this.mFolderVerCounterLow = countLow; } public byte[] getFolderVerCounter() { if (mFolderVerCounterHigh != INVALID_VALUE_PARAMETER && mFolderVerCounterLow != INVALID_VALUE_PARAMETER) { ByteBuffer ret = ByteBuffer.allocate(16); ret.putLong(mFolderVerCounterHigh); ret.putLong(mFolderVerCounterLow); return ret.array(); } else { return null; } } public SignedLongLong getChatStateConvoId() { return mChatStateConvoId; } public byte[] getChatStateConvoIdByteArray() { if (mChatStateConvoId != null) { ByteBuffer ret = ByteBuffer.allocate(16); ret.putLong(mChatStateConvoId.getMostSignificantBits()); ret.putLong(mChatStateConvoId.getLeastSignificantBits()); return ret.array(); } else { return null; } } public String getChatStateConvoIdString() { String str = null; str = new String(this.getChatStateConvoIdByteArray()); return str; } public void setChatStateConvoId(long idHigh, long idLow) { mChatStateConvoId = new SignedLongLong(idLow, idHigh); } public void setFilterMsgHandle(String handle) { try { mFilterMsgHandle = BluetoothMapUtils.getLongFromString(handle); } catch (UnsupportedEncodingException | NumberFormatException e) { Log.w(TAG, "Error creating long from handle string", e); } } public long getFilterMsgHandle() { return mFilterMsgHandle; } public String getFilterMsgHandleString() { String str = null; if (mFilterMsgHandle != INVALID_VALUE_PARAMETER) { str = BluetoothMapUtils.getLongAsString(mFilterMsgHandle); } return str; } public int getFilterUidPresent() { return mFilterUidPresent; } public void setFilterUidPresent(int present) { if (present < 0 || present > 0x00FF) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); } this.mFilterUidPresent = present; } public int getFilterPresence() { return mFilterPresence; } public SignedLongLong getFilterConvoId() { return mFilterConvoId; } /** * Get a decimal representation of the lower bits of the ConvoId - used for queries. * The upper bits are used for convo-type. * @return decimal representation of the convo ID. */ public String getFilterConvoIdString() { String str = null; if (mFilterConvoId != null) { str = BluetoothMapUtils.getLongAsString(mFilterConvoId.getLeastSignificantBits()); } return str; } public void setFilterConvoId(String id) { try { mFilterConvoId = SignedLongLong.fromString(id); } catch (UnsupportedEncodingException | NumberFormatException e) { Log.w(TAG, "Error creating long from id string", e); } } public void setChatState(int state) { if (state < 0 || state > 0x00FF) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); } this.mChatState = state; } public int getChatState() { return mChatState; } public long getLastActivity() { return this.mLastActivity; } public String getLastActivityString() { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); Date date = new Date(mLastActivity); return format.format(date); // Format to YYYYMMDDTHHMMSS local time } public void setLastActivity(long last) { this.mLastActivity = last; } public void setLastActivity(String lastActivity) throws ParseException { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); Date date = format.parse(lastActivity); this.mLastActivity = date.getTime(); } public void setPresenceStatus(String status) { this.mPresenceStatus = status; } public String getPresenceStatus() { return this.mPresenceStatus; } public void setFilterPresence(int presence) { if (presence < 0 || presence > 0xFFFF) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); } this.mFilterPresence = presence; } public void setPresenceAvailability(int availability) { if (availability < 0 || availability > 0x00FF) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); } this.mPresenceAvailability = availability; } public int getPresenceAvailability() { return mPresenceAvailability; } public int getSubjectLength() { return mSubjectLength; } public int getAttachment() { return mAttachment; } public void setAttachment(int attachment) throws IllegalArgumentException { if (attachment < 0 || attachment > 0x0001) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); } this.mAttachment = attachment; } public int getTransparent() { return mTransparent; } public void setTransparent(int transparent) throws IllegalArgumentException { if (transparent < 0 || transparent > 0x0001) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); } this.mTransparent = transparent; } public int getRetry() { return mRetry; } public void setRetry(int retry) throws IllegalArgumentException { if (retry < 0 || retry > 0x0001) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); } this.mRetry = retry; } public int getNewMessage() { return mNewMessage; } public void setNewMessage(int newMessage) throws IllegalArgumentException { if (newMessage < 0 || newMessage > 0x0001) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); } this.mNewMessage = newMessage; } public int getNotificationStatus() { return mNotificationStatus; } public void setNotificationStatus(int notificationStatus) throws IllegalArgumentException { if (notificationStatus < 0 || notificationStatus > 0x0001) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); } this.mNotificationStatus = notificationStatus; } public long getNotificationFilter() { return mNotificationFilter; } public void setNotificationFilter(long notificationFilter) throws IllegalArgumentException { if (notificationFilter < 0 || notificationFilter > 0xFFFFFFFFL) { throw new IllegalArgumentException( "Out of range, valid range is 0x0000 to 0xFFFFFFFFL"); } this.mNotificationFilter = notificationFilter; } public int getMasInstanceId() { return mMasInstanceId; } public void setMasInstanceId(int masInstanceId) { if (masInstanceId < 0 || masInstanceId > 0x00FF) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); } this.mMasInstanceId = masInstanceId; } public long getParameterMask() { return mParameterMask; } public void setParameterMask(long parameterMask) { if (parameterMask < 0 || parameterMask > 0xFFFFFFFFL) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFFFFFF"); } this.mParameterMask = parameterMask; } public void setConvoParameterMask(long parameterMask) { if (parameterMask < 0 || parameterMask > 0xFFFFFFFFL) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFFFFFF"); } this.mConvoParameterMask = parameterMask; } public long getConvoParameterMask() { return mConvoParameterMask; } public int getFolderListingSize() { return mFolderListingSize; } public void setFolderListingSize(int folderListingSize) { if (folderListingSize < 0 || folderListingSize > 0xFFFF) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); } this.mFolderListingSize = folderListingSize; } public int getMessageListingSize() { return mMessageListingSize; } public void setMessageListingSize(int messageListingSize) { if (messageListingSize < 0 || messageListingSize > 0xFFFF) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); } this.mMessageListingSize = messageListingSize; } public int getConvoListingSize() { return mConvoListingSize; } public void setConvoListingSize(int convoListingSize) { if (convoListingSize < 0 || convoListingSize > 0xFFFF) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0xFFFF"); } this.mConvoListingSize = convoListingSize; } public void setSubjectLength(int subjectLength) { if (subjectLength < 0 || subjectLength > 0xFF) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x00FF"); } this.mSubjectLength = subjectLength; } public int getCharset() { return mCharset; } public void setCharset(int charset) { if (charset < 0 || charset > 0x1) { throw new IllegalArgumentException( "Out of range: " + charset + ", valid range is 0x0000 to 0x0001"); } this.mCharset = charset; } public int getFractionRequest() { return mFractionRequest; } public void setFractionRequest(int fractionRequest) { if (fractionRequest < 0 || fractionRequest > 0x1) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); } this.mFractionRequest = fractionRequest; } public int getFractionDeliver() { return mFractionDeliver; } public void setFractionDeliver(int fractionDeliver) { if (fractionDeliver < 0 || fractionDeliver > 0x1) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); } this.mFractionDeliver = fractionDeliver; } public int getStatusIndicator() { return mStatusIndicator; } public void setStatusIndicator(int statusIndicator) { if (statusIndicator < 0 || statusIndicator > 0x1) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); } this.mStatusIndicator = statusIndicator; } public int getStatusValue() { return mStatusValue; } public void setStatusValue(int statusValue) { if (statusValue < 0 || statusValue > 0x1) { throw new IllegalArgumentException("Out of range, valid range is 0x0000 to 0x0001"); } this.mStatusValue = statusValue; } public long getMseTime() { return mMseTime; } public String getMseTimeString() { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); Date date = new Date(getMseTime()); return format.format(date); // Format to YYYYMMDDTHHMMSS±hhmm UTC time ± offset } public void setMseTime(long mseTime) { this.mMseTime = mseTime; } public void setMseTime(String mseTime) throws ParseException { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); Date date = format.parse(mseTime); this.mMseTime = date.getTime(); } }