• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.bluetooth.client.map;
18 import android.util.Log;
19 
20 import org.json.JSONException;
21 import org.json.JSONObject;
22 import org.xmlpull.v1.XmlPullParser;
23 import org.xmlpull.v1.XmlPullParserException;
24 import org.xmlpull.v1.XmlPullParserFactory;
25 
26 import java.io.DataInputStream;
27 import java.io.IOException;
28 import java.math.BigInteger;
29 import java.util.HashMap;
30 
31 /**
32  * Object representation of event report received by MNS
33  * <p>
34  * This object will be received in {@link BluetoothMasClient#EVENT_EVENT_REPORT}
35  * callback message.
36  */
37 public class BluetoothMapEventReport {
38 
39     private final static String TAG = "BluetoothMapEventReport";
40 
41     public enum Type {
42         NEW_MESSAGE("NewMessage"), DELIVERY_SUCCESS("DeliverySuccess"),
43         SENDING_SUCCESS("SendingSuccess"), DELIVERY_FAILURE("DeliveryFailure"),
44         SENDING_FAILURE("SendingFailure"), MEMORY_FULL("MemoryFull"),
45         MEMORY_AVAILABLE("MemoryAvailable"), MESSAGE_DELETED("MessageDeleted"),
46         MESSAGE_SHIFT("MessageShift");
47 
48         private final String mSpecName;
49 
Type(String specName)50         private Type(String specName) {
51             mSpecName = specName;
52         }
53 
54         @Override
toString()55         public String toString() {
56             return mSpecName;
57         }
58     }
59 
60     private final Type mType;
61 
62     private final String mHandle;
63 
64     private final String mFolder;
65 
66     private final String mOldFolder;
67 
68     private final BluetoothMapBmessage.Type mMsgType;
69 
BluetoothMapEventReport(HashMap<String, String> attrs)70     private BluetoothMapEventReport(HashMap<String, String> attrs) throws IllegalArgumentException {
71         mType = parseType(attrs.get("type"));
72 
73         if (mType != Type.MEMORY_FULL && mType != Type.MEMORY_AVAILABLE) {
74             String handle = attrs.get("handle");
75             try {
76                 /* just to validate */
77                 new BigInteger(attrs.get("handle"), 16);
78 
79                 mHandle = attrs.get("handle");
80             } catch (NumberFormatException e) {
81                 throw new IllegalArgumentException("Invalid value for handle:" + handle);
82             }
83         } else {
84             mHandle = null;
85         }
86 
87         mFolder = attrs.get("folder");
88 
89         mOldFolder = attrs.get("old_folder");
90 
91         if (mType != Type.MEMORY_FULL && mType != Type.MEMORY_AVAILABLE) {
92             String s = attrs.get("msg_type");
93 
94             if ("".equals(s)) {
95                 // Some phones (e.g. SGS3 for MessageDeleted) send empty
96                 // msg_type, in such case leave it as null rather than throw
97                 // parse exception
98                 mMsgType = null;
99             } else {
100                 mMsgType = parseMsgType(s);
101             }
102         } else {
103             mMsgType = null;
104         }
105     }
106 
parseType(String type)107     private Type parseType(String type) throws IllegalArgumentException {
108         for (Type t : Type.values()) {
109             if (t.toString().equals(type)) {
110                 return t;
111             }
112         }
113 
114         throw new IllegalArgumentException("Invalid value for type: " + type);
115     }
116 
parseMsgType(String msgType)117     private BluetoothMapBmessage.Type parseMsgType(String msgType) throws IllegalArgumentException {
118         for (BluetoothMapBmessage.Type t : BluetoothMapBmessage.Type.values()) {
119             if (t.name().equals(msgType)) {
120                 return t;
121             }
122         }
123 
124         throw new IllegalArgumentException("Invalid value for msg_type: " + msgType);
125     }
126 
127     /**
128      * @return {@link BluetoothMapEventReport.Type} object corresponding to
129      *         <code>type</code> application parameter in MAP specification
130      */
getType()131     public Type getType() {
132         return mType;
133     }
134 
135     /**
136      * @return value corresponding to <code>handle</code> parameter in MAP
137      *         specification
138      */
getHandle()139     public String getHandle() {
140         return mHandle;
141     }
142 
143     /**
144      * @return value corresponding to <code>folder</code> parameter in MAP
145      *         specification
146      */
getFolder()147     public String getFolder() {
148         return mFolder;
149     }
150 
151     /**
152      * @return value corresponding to <code>old_folder</code> parameter in MAP
153      *         specification
154      */
getOldFolder()155     public String getOldFolder() {
156         return mOldFolder;
157     }
158 
159     /**
160      * @return {@link BluetoothMapBmessage.Type} object corresponding to
161      *         <code>msg_type</code> application parameter in MAP specification
162      */
getMsgType()163     public BluetoothMapBmessage.Type getMsgType() {
164         return mMsgType;
165     }
166 
167     @Override
toString()168     public String toString() {
169         JSONObject json = new JSONObject();
170 
171         try {
172             json.put("type", mType);
173             json.put("handle", mHandle);
174             json.put("folder", mFolder);
175             json.put("old_folder", mOldFolder);
176             json.put("msg_type", mMsgType);
177         } catch (JSONException e) {
178             // do nothing
179         }
180 
181         return json.toString();
182     }
183 
fromStream(DataInputStream in)184     static BluetoothMapEventReport fromStream(DataInputStream in) {
185         BluetoothMapEventReport ev = null;
186 
187         try {
188             XmlPullParser xpp = XmlPullParserFactory.newInstance().newPullParser();
189             xpp.setInput(in, "utf-8");
190 
191             int event = xpp.getEventType();
192             while (event != XmlPullParser.END_DOCUMENT) {
193                 switch (event) {
194                     case XmlPullParser.START_TAG:
195                         if (xpp.getName().equals("event")) {
196                             HashMap<String, String> attrs = new HashMap<String, String>();
197 
198                             for (int i = 0; i < xpp.getAttributeCount(); i++) {
199                                 attrs.put(xpp.getAttributeName(i), xpp.getAttributeValue(i));
200                             }
201 
202                             ev = new BluetoothMapEventReport(attrs);
203 
204                             // return immediately, only one event should be here
205                             return ev;
206                         }
207                         break;
208                 }
209 
210                 event = xpp.next();
211             }
212 
213         } catch (XmlPullParserException e) {
214             Log.e(TAG, "XML parser error when parsing XML", e);
215         } catch (IOException e) {
216             Log.e(TAG, "I/O error when parsing XML", e);
217         } catch (IllegalArgumentException e) {
218             Log.e(TAG, "Invalid event received", e);
219         }
220 
221         return ev;
222     }
223 }
224