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 com.android.bluetooth.DeviceWorkArounds;
18 import com.android.bluetooth.map.BluetoothMapUtils.TYPE;
19 
20 import org.xmlpull.v1.XmlSerializer;
21 
22 import java.io.IOException;
23 import java.text.SimpleDateFormat;
24 import java.util.Date;
25 
26 public class BluetoothMapMessageListingElement
27         implements Comparable<BluetoothMapMessageListingElement> {
28 
29     private static final String TAG = "BluetoothMapMessageListingElement";
30 
31     private long mCpHandle = 0; /* The content provider handle - without type information */
32     private String mSubject = null;
33     private long mDateTime = 0;
34     private String mSenderName = null;
35     private String mSenderAddressing = null;
36     private String mReplytoAddressing = null;
37     private String mRecipientName = null;
38     private String mRecipientAddressing = null;
39     private TYPE mType = null;
40     private boolean mMsgTypeAppParamSet = false;
41     private int mSize = -1;
42     private String mText = null;
43     private String mReceptionStatus = null;
44     private String mDeliveryStatus = null;
45     private int mAttachmentSize = -1;
46     private String mPriority = null;
47     private boolean mRead = false;
48     private String mSent = null;
49     private String mProtect = null;
50     private String mFolderType = null;
51     private String mThreadId = null;
52     private String mThreadName = null;
53     private String mAttachmentMimeTypes = null;
54 
55     private boolean mReportRead = false;
56     private int mCursorIndex = 0;
57 
getCursorIndex()58     public int getCursorIndex() {
59         return mCursorIndex;
60     }
61 
setCursorIndex(int cursorIndex)62     public void setCursorIndex(int cursorIndex) {
63         this.mCursorIndex = cursorIndex;
64     }
65 
getHandle()66     public long getHandle() {
67         return mCpHandle;
68     }
69 
setHandle(long handle)70     public void setHandle(long handle) {
71         this.mCpHandle = handle;
72     }
73 
getDateTime()74     public long getDateTime() {
75         return mDateTime;
76     }
77 
getDateTimeString()78     public String getDateTimeString() {
79         /* TODO: if the feature bit mask of the client supports it, add the time-zone
80          *       (as for MSETime) */
81         SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
82         Date date = new Date(mDateTime);
83         return format.format(date); // Format to YYYYMMDDTHHMMSS local time
84     }
85 
setDateTime(long dateTime)86     public void setDateTime(long dateTime) {
87         this.mDateTime = dateTime;
88     }
89 
getSubject()90     public String getSubject() {
91         return mSubject;
92     }
93 
setSubject(String subject)94     public void setSubject(String subject) {
95         this.mSubject = subject;
96     }
97 
getSenderName()98     public String getSenderName() {
99         return mSenderName;
100     }
101 
setSenderName(String senderName)102     public void setSenderName(String senderName) {
103         this.mSenderName = senderName;
104     }
105 
getSenderAddressing()106     public String getSenderAddressing() {
107         return mSenderAddressing;
108     }
109 
setSenderAddressing(String senderAddressing)110     public void setSenderAddressing(String senderAddressing) {
111         this.mSenderAddressing = senderAddressing;
112     }
113 
getReplyToAddressing()114     public String getReplyToAddressing() {
115         return mReplytoAddressing;
116     }
117 
setReplytoAddressing(String replytoAddressing)118     public void setReplytoAddressing(String replytoAddressing) {
119         this.mReplytoAddressing = replytoAddressing;
120     }
121 
getRecipientName()122     public String getRecipientName() {
123         return mRecipientName;
124     }
125 
setRecipientName(String recipientName)126     public void setRecipientName(String recipientName) {
127         this.mRecipientName = recipientName;
128     }
129 
getRecipientAddressing()130     public String getRecipientAddressing() {
131         return mRecipientAddressing;
132     }
133 
setRecipientAddressing(String recipientAddressing)134     public void setRecipientAddressing(String recipientAddressing) {
135         this.mRecipientAddressing = recipientAddressing;
136     }
137 
getType()138     public TYPE getType() {
139         return mType;
140     }
141 
setType(TYPE type, boolean appParamSet)142     public void setType(TYPE type, boolean appParamSet) {
143         this.mMsgTypeAppParamSet = appParamSet;
144         this.mType = type;
145     }
146 
getSize()147     public int getSize() {
148         return mSize;
149     }
150 
setSize(int size)151     public void setSize(int size) {
152         this.mSize = size;
153     }
154 
getText()155     public String getText() {
156         return mText;
157     }
158 
setText(String text)159     public void setText(String text) {
160         this.mText = text;
161     }
162 
getReceptionStatus()163     public String getReceptionStatus() {
164         return mReceptionStatus;
165     }
166 
setReceptionStatus(String receptionStatus)167     public void setReceptionStatus(String receptionStatus) {
168         this.mReceptionStatus = receptionStatus;
169     }
170 
getDeliveryStatus()171     public String getDeliveryStatus() {
172         return mDeliveryStatus;
173     }
174 
setDeliveryStatus(String deliveryStatus)175     public void setDeliveryStatus(String deliveryStatus) {
176         this.mDeliveryStatus = deliveryStatus;
177     }
178 
getAttachmentSize()179     public int getAttachmentSize() {
180         return mAttachmentSize;
181     }
182 
setAttachmentSize(int attachmentSize)183     public void setAttachmentSize(int attachmentSize) {
184         this.mAttachmentSize = attachmentSize;
185     }
186 
getAttachmentMimeTypes()187     public String getAttachmentMimeTypes() {
188         return mAttachmentMimeTypes;
189     }
190 
setAttachmentMimeTypes(String attachmentMimeTypes)191     public void setAttachmentMimeTypes(String attachmentMimeTypes) {
192         this.mAttachmentMimeTypes = attachmentMimeTypes;
193     }
194 
getPriority()195     public String getPriority() {
196         return mPriority;
197     }
198 
setPriority(String priority)199     public void setPriority(String priority) {
200         this.mPriority = priority;
201     }
202 
getRead()203     public String getRead() {
204         return (mRead ? "yes" : "no");
205     }
206 
getReadBool()207     public boolean getReadBool() {
208         return mRead;
209     }
210 
setRead(boolean read, boolean reportRead)211     public void setRead(boolean read, boolean reportRead) {
212         this.mRead = read;
213         this.mReportRead = reportRead;
214     }
215 
getSent()216     public String getSent() {
217         return mSent;
218     }
219 
setSent(String sent)220     public void setSent(String sent) {
221         this.mSent = sent;
222     }
223 
getProtect()224     public String getProtect() {
225         return mProtect;
226     }
227 
setProtect(String protect)228     public void setProtect(String protect) {
229         this.mProtect = protect;
230     }
231 
setThreadId(long threadId, TYPE type)232     public void setThreadId(long threadId, TYPE type) {
233         if (threadId != -1) {
234             this.mThreadId = BluetoothMapUtils.getMapConvoHandle(threadId, type);
235         }
236     }
237 
getThreadName()238     public String getThreadName() {
239         return mThreadName;
240     }
241 
setThreadName(String name)242     public void setThreadName(String name) {
243         this.mThreadName = name;
244     }
245 
getFolderType()246     public String getFolderType() {
247         return mFolderType;
248     }
249 
setFolderType(String folderType)250     public void setFolderType(String folderType) {
251         this.mFolderType = folderType;
252     }
253 
254     @Override
compareTo(BluetoothMapMessageListingElement e)255     public int compareTo(BluetoothMapMessageListingElement e) {
256         if (this.mDateTime < e.mDateTime) {
257             return 1;
258         } else if (this.mDateTime > e.mDateTime) {
259             return -1;
260         } else {
261             return 0;
262         }
263     }
264 
265     /* Encode the MapMessageListingElement into the StringBuilder reference.
266      * */
encode(XmlSerializer xmlMsgElement, boolean includeThreadId)267     public void encode(XmlSerializer xmlMsgElement, boolean includeThreadId)
268             throws IllegalArgumentException, IllegalStateException, IOException {
269         // contruct the XML tag for a single msg in the msglisting
270         xmlMsgElement.startTag(null, "msg");
271         xmlMsgElement.attribute(null, "handle", BluetoothMapUtils.getMapHandle(mCpHandle, mType));
272         if (mSubject != null) {
273             String stripped = BluetoothMapUtils.stripInvalidChars(mSubject);
274 
275             if (DeviceWorkArounds.addressStartsWith(
276                     BluetoothMapService.getRemoteDevice().getAddress(),
277                     DeviceWorkArounds.MERCEDES_BENZ_CARKIT)) {
278                 stripped = stripped.replaceAll("[\\P{ASCII}&\"><]", "");
279                 if (stripped.isEmpty()) {
280                     stripped = "---";
281                 }
282             }
283 
284             xmlMsgElement.attribute(
285                     null,
286                     "subject",
287                     stripped.substring(0, stripped.length() < 256 ? stripped.length() : 256));
288         }
289 
290         if (mDateTime != 0) {
291             xmlMsgElement.attribute(
292                     null, "datetime", BluetoothMapUtils.getDateTimeString(this.getDateTime()));
293         }
294         if (mSenderName != null) {
295             xmlMsgElement.attribute(
296                     null, "sender_name", BluetoothMapUtils.stripInvalidChars(mSenderName));
297         }
298         if (mSenderAddressing != null) {
299             xmlMsgElement.attribute(null, "sender_addressing", mSenderAddressing);
300         }
301         if (mReplytoAddressing != null) {
302             xmlMsgElement.attribute(null, "replyto_addressing", mReplytoAddressing);
303         }
304         if (mRecipientName != null) {
305             xmlMsgElement.attribute(
306                     null, "recipient_name", BluetoothMapUtils.stripInvalidChars(mRecipientName));
307         }
308         if (mRecipientAddressing != null) {
309             xmlMsgElement.attribute(null, "recipient_addressing", mRecipientAddressing);
310         }
311         /* Avoid NPE for possible "null" value of mType */
312         if (mMsgTypeAppParamSet && mType != null) {
313             xmlMsgElement.attribute(null, "type", mType.name());
314         }
315         if (mSize != -1) {
316             xmlMsgElement.attribute(null, "size", Integer.toString(mSize));
317         }
318         if (mText != null) {
319             xmlMsgElement.attribute(null, "text", mText);
320         }
321         if (mReceptionStatus != null) {
322             xmlMsgElement.attribute(null, "reception_status", mReceptionStatus);
323         }
324         if (mDeliveryStatus != null) {
325             xmlMsgElement.attribute(null, "delivery_status", mDeliveryStatus);
326         }
327         if (mAttachmentSize != -1) {
328             xmlMsgElement.attribute(null, "attachment_size", Integer.toString(mAttachmentSize));
329         }
330         if (mAttachmentMimeTypes != null) {
331             xmlMsgElement.attribute(null, "attachment_mime_types", mAttachmentMimeTypes);
332         }
333         if (mPriority != null) {
334             xmlMsgElement.attribute(null, "priority", mPriority);
335         }
336         if (mReportRead) {
337             xmlMsgElement.attribute(null, "read", getRead());
338         }
339         if (mSent != null) {
340             xmlMsgElement.attribute(null, "sent", mSent);
341         }
342         if (mProtect != null) {
343             xmlMsgElement.attribute(null, "protected", mProtect);
344         }
345         if (mThreadId != null && includeThreadId) {
346             xmlMsgElement.attribute(null, "conversation_id", mThreadId);
347         }
348         if (mThreadName != null && includeThreadId) {
349             xmlMsgElement.attribute(null, "conversation_name", mThreadName);
350         }
351         if (mFolderType != null) {
352             xmlMsgElement.attribute(null, "folder_type", mFolderType);
353         }
354         xmlMsgElement.endTag(null, "msg");
355     }
356 }
357