/* * Copyright (C) 2014 The Android Open Source Project * * 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 android.bluetooth.client.map; import android.util.Log; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import java.io.DataInputStream; import java.io.IOException; import java.math.BigInteger; import java.util.HashMap; /** * Object representation of event report received by MNS * <p> * This object will be received in {@link BluetoothMasClient#EVENT_EVENT_REPORT} * callback message. */ public class BluetoothMapEventReport { private final static String TAG = "BluetoothMapEventReport"; public enum Type { NEW_MESSAGE("NewMessage"), DELIVERY_SUCCESS("DeliverySuccess"), SENDING_SUCCESS("SendingSuccess"), DELIVERY_FAILURE("DeliveryFailure"), SENDING_FAILURE("SendingFailure"), MEMORY_FULL("MemoryFull"), MEMORY_AVAILABLE("MemoryAvailable"), MESSAGE_DELETED("MessageDeleted"), MESSAGE_SHIFT("MessageShift"); private final String mSpecName; private Type(String specName) { mSpecName = specName; } @Override public String toString() { return mSpecName; } } private final Type mType; private final String mHandle; private final String mFolder; private final String mOldFolder; private final BluetoothMapBmessage.Type mMsgType; private BluetoothMapEventReport(HashMap<String, String> attrs) throws IllegalArgumentException { mType = parseType(attrs.get("type")); if (mType != Type.MEMORY_FULL && mType != Type.MEMORY_AVAILABLE) { String handle = attrs.get("handle"); try { /* just to validate */ new BigInteger(attrs.get("handle"), 16); mHandle = attrs.get("handle"); } catch (NumberFormatException e) { throw new IllegalArgumentException("Invalid value for handle:" + handle); } } else { mHandle = null; } mFolder = attrs.get("folder"); mOldFolder = attrs.get("old_folder"); if (mType != Type.MEMORY_FULL && mType != Type.MEMORY_AVAILABLE) { String s = attrs.get("msg_type"); if ("".equals(s)) { // Some phones (e.g. SGS3 for MessageDeleted) send empty // msg_type, in such case leave it as null rather than throw // parse exception mMsgType = null; } else { mMsgType = parseMsgType(s); } } else { mMsgType = null; } } private Type parseType(String type) throws IllegalArgumentException { for (Type t : Type.values()) { if (t.toString().equals(type)) { return t; } } throw new IllegalArgumentException("Invalid value for type: " + type); } private BluetoothMapBmessage.Type parseMsgType(String msgType) throws IllegalArgumentException { for (BluetoothMapBmessage.Type t : BluetoothMapBmessage.Type.values()) { if (t.name().equals(msgType)) { return t; } } throw new IllegalArgumentException("Invalid value for msg_type: " + msgType); } /** * @return {@link BluetoothMapEventReport.Type} object corresponding to * <code>type</code> application parameter in MAP specification */ public Type getType() { return mType; } /** * @return value corresponding to <code>handle</code> parameter in MAP * specification */ public String getHandle() { return mHandle; } /** * @return value corresponding to <code>folder</code> parameter in MAP * specification */ public String getFolder() { return mFolder; } /** * @return value corresponding to <code>old_folder</code> parameter in MAP * specification */ public String getOldFolder() { return mOldFolder; } /** * @return {@link BluetoothMapBmessage.Type} object corresponding to * <code>msg_type</code> application parameter in MAP specification */ public BluetoothMapBmessage.Type getMsgType() { return mMsgType; } @Override public String toString() { JSONObject json = new JSONObject(); try { json.put("type", mType); json.put("handle", mHandle); json.put("folder", mFolder); json.put("old_folder", mOldFolder); json.put("msg_type", mMsgType); } catch (JSONException e) { // do nothing } return json.toString(); } static BluetoothMapEventReport fromStream(DataInputStream in) { BluetoothMapEventReport ev = null; try { XmlPullParser xpp = XmlPullParserFactory.newInstance().newPullParser(); xpp.setInput(in, "utf-8"); int event = xpp.getEventType(); while (event != XmlPullParser.END_DOCUMENT) { switch (event) { case XmlPullParser.START_TAG: if (xpp.getName().equals("event")) { HashMap<String, String> attrs = new HashMap<String, String>(); for (int i = 0; i < xpp.getAttributeCount(); i++) { attrs.put(xpp.getAttributeName(i), xpp.getAttributeValue(i)); } ev = new BluetoothMapEventReport(attrs); // return immediately, only one event should be here return ev; } break; } event = xpp.next(); } } catch (XmlPullParserException e) { Log.e(TAG, "XML parser error when parsing XML", e); } catch (IOException e) { Log.e(TAG, "I/O error when parsing XML", e); } catch (IllegalArgumentException e) { Log.e(TAG, "Invalid event received", e); } return ev; } }