diff options
author | Hansong Zhang <hsz@google.com> | 2018-01-02 11:43:18 -0800 |
---|---|---|
committer | Hansong Zhang <hsz@google.com> | 2018-01-02 11:43:18 -0800 |
commit | 9298381a4ede0c9c647c006be6ef1446f3a9686d (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 | |
parent | c117d79c0968400698712e9b714ad272eaeb8fc3 (diff) | |
download | bluetooth-o-mr1-iot-preview-8.tar.gz |
Remove frameworks/opt/bluetoothHEADandroid-o-mr1-iot-release-smart-display-r9android-o-mr1-iot-release-smart-display-r8android-o-mr1-iot-release-smart-display-r5android-o-mr1-iot-release-smart-display-r40.1Jandroid-o-mr1-iot-release-smart-display-r4android-o-mr1-iot-release-smart-display-r39android-o-mr1-iot-release-smart-display-r30android-o-mr1-iot-release-smart-display-r3android-o-mr1-iot-release-smart-display-r22android-o-mr1-iot-release-smart-display-r14android-o-mr1-iot-release-smart-clock-r6android-o-mr1-iot-release-smart-clock-r2android-o-mr1-iot-release-smart-clock-fsiandroid-o-mr1-iot-release-smart-clock-fcsandroid-o-mr1-iot-release-cube_r2android-o-mr1-iot-release-cube-fsiandroid-o-mr1-iot-release-cube-fcsandroid-o-mr1-iot-release-1.0.8android-o-mr1-iot-release-1.0.7android-o-mr1-iot-release-1.0.5android-o-mr1-iot-release-1.0.4android-o-mr1-iot-release-1.0.3android-o-mr1-iot-release-1.0.2android-o-mr1-iot-release-1.0.14android-o-mr1-iot-release-1.0.13android-o-mr1-iot-release-1.0.12android-o-mr1-iot-release-1.0.10android-o-mr1-iot-release-1.0.1android-o-mr1-iot-release-1.0.0android-o-mr1-iot-preview-8android-o-mr1-iot-preview-7android-n-iot-release-smart-display-r2android-n-iot-release-smart-displayandroid-n-iot-release-polk-at1android-n-iot-release-lg-thinq-wk7android-n-iot-release-ihome-igv1oreo-mr1-iot-releaseoreo-mr1-1.2-iot-releaseo-mr1-iot-preview-8o-mr1-iot-preview-7nougat-iot-releasemastermain
This project is no longer used.
Test: make
Change-Id: If186da10598c4bb41331f1d1f4e9810fe666caa0
28 files changed, 0 insertions, 4525 deletions
diff --git a/Android.mk b/Android.mk deleted file mode 100644 index 866d84a..0000000 --- a/Android.mk +++ /dev/null @@ -1,18 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -src_dirs:= src/android/bluetooth/client/map - -LOCAL_SRC_FILES := \ - $(call all-java-files-under, $(src_dirs)) - -LOCAL_MODULE:= android.bluetooth.client.map -LOCAL_JAVA_LIBRARIES := javax.obex -LOCAL_STATIC_JAVA_LIBRARIES := com.android.vcard - -LOCAL_PROGUARD_ENABLED := disabled - -include $(BUILD_STATIC_JAVA_LIBRARY) - - -include $(call all-makefiles-under,$(LOCAL_PATH)) @@ -1 +0,0 @@ -pirozzoj@google.com diff --git a/src/android/bluetooth/client/map/BluetoothMapBmessage.java b/src/android/bluetooth/client/map/BluetoothMapBmessage.java deleted file mode 100644 index e06b033..0000000 --- a/src/android/bluetooth/client/map/BluetoothMapBmessage.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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 com.android.vcard.VCardEntry; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; - -/** - * Object representation of message in bMessage format - * <p> - * This object will be received in {@link BluetoothMasClient#EVENT_GET_MESSAGE} - * callback message. - */ -public class BluetoothMapBmessage { - - String mBmsgVersion; - Status mBmsgStatus; - Type mBmsgType; - String mBmsgFolder; - - String mBbodyEncoding; - String mBbodyCharset; - String mBbodyLanguage; - int mBbodyLength; - - String mMessage; - - ArrayList<VCardEntry> mOriginators; - ArrayList<VCardEntry> mRecipients; - - public enum Status { - READ, UNREAD - } - - public enum Type { - EMAIL, SMS_GSM, SMS_CDMA, MMS - } - - /** - * Constructs empty message object - */ - public BluetoothMapBmessage() { - mOriginators = new ArrayList<VCardEntry>(); - mRecipients = new ArrayList<VCardEntry>(); - } - - public VCardEntry getOriginator() { - if (mOriginators.size() > 0) { - return mOriginators.get(0); - } else { - return null; - } - } - - public ArrayList<VCardEntry> getOriginators() { - return mOriginators; - } - - public BluetoothMapBmessage addOriginator(VCardEntry vcard) { - mOriginators.add(vcard); - return this; - } - - public ArrayList<VCardEntry> getRecipients() { - return mRecipients; - } - - public BluetoothMapBmessage addRecipient(VCardEntry vcard) { - mRecipients.add(vcard); - return this; - } - - public Status getStatus() { - return mBmsgStatus; - } - - public BluetoothMapBmessage setStatus(Status status) { - mBmsgStatus = status; - return this; - } - - public Type getType() { - return mBmsgType; - } - - public BluetoothMapBmessage setType(Type type) { - mBmsgType = type; - return this; - } - - public String getFolder() { - return mBmsgFolder; - } - - public BluetoothMapBmessage setFolder(String folder) { - mBmsgFolder = folder; - return this; - } - - public String getEncoding() { - return mBbodyEncoding; - } - - public BluetoothMapBmessage setEncoding(String encoding) { - mBbodyEncoding = encoding; - return this; - } - - public String getCharset() { - return mBbodyCharset; - } - - public BluetoothMapBmessage setCharset(String charset) { - mBbodyCharset = charset; - return this; - } - - public String getLanguage() { - return mBbodyLanguage; - } - - public BluetoothMapBmessage setLanguage(String language) { - mBbodyLanguage = language; - return this; - } - - public String getBodyContent() { - return mMessage; - } - - public BluetoothMapBmessage setBodyContent(String body) { - mMessage = body; - return this; - } - - @Override - public String toString() { - JSONObject json = new JSONObject(); - - try { - json.put("status", mBmsgStatus); - json.put("type", mBmsgType); - json.put("folder", mBmsgFolder); - json.put("charset", mBbodyCharset); - json.put("message", mMessage); - } catch (JSONException e) { - // do nothing - } - - return json.toString(); - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMapBmessageBuilder.java b/src/android/bluetooth/client/map/BluetoothMapBmessageBuilder.java deleted file mode 100644 index 8629423..0000000 --- a/src/android/bluetooth/client/map/BluetoothMapBmessageBuilder.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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 com.android.vcard.VCardEntry; -import com.android.vcard.VCardEntry.EmailData; -import com.android.vcard.VCardEntry.NameData; -import com.android.vcard.VCardEntry.PhoneData; - -import java.util.List; - -class BluetoothMapBmessageBuilder { - - private final static String CRLF = "\r\n"; - - private final static String BMSG_BEGIN = "BEGIN:BMSG"; - private final static String BMSG_VERSION = "VERSION:1.0"; - private final static String BMSG_STATUS = "STATUS:"; - private final static String BMSG_TYPE = "TYPE:"; - private final static String BMSG_FOLDER = "FOLDER:"; - private final static String BMSG_END = "END:BMSG"; - - private final static String BENV_BEGIN = "BEGIN:BENV"; - private final static String BENV_END = "END:BENV"; - - private final static String BBODY_BEGIN = "BEGIN:BBODY"; - private final static String BBODY_ENCODING = "ENCODING:"; - private final static String BBODY_CHARSET = "CHARSET:"; - private final static String BBODY_LANGUAGE = "LANGUAGE:"; - private final static String BBODY_LENGTH = "LENGTH:"; - private final static String BBODY_END = "END:BBODY"; - - private final static String MSG_BEGIN = "BEGIN:MSG"; - private final static String MSG_END = "END:MSG"; - - private final static String VCARD_BEGIN = "BEGIN:VCARD"; - private final static String VCARD_VERSION = "VERSION:2.1"; - private final static String VCARD_N = "N:"; - private final static String VCARD_EMAIL = "EMAIL:"; - private final static String VCARD_TEL = "TEL:"; - private final static String VCARD_END = "END:VCARD"; - - private final StringBuilder mBmsg; - - private BluetoothMapBmessageBuilder() { - mBmsg = new StringBuilder(); - } - - static public String createBmessage(BluetoothMapBmessage bmsg) { - BluetoothMapBmessageBuilder b = new BluetoothMapBmessageBuilder(); - - b.build(bmsg); - - return b.mBmsg.toString(); - } - - private void build(BluetoothMapBmessage bmsg) { - int bodyLen = MSG_BEGIN.length() + MSG_END.length() + 3 * CRLF.length() - + bmsg.mMessage.getBytes().length; - - mBmsg.append(BMSG_BEGIN).append(CRLF); - - mBmsg.append(BMSG_VERSION).append(CRLF); - mBmsg.append(BMSG_STATUS).append(bmsg.mBmsgStatus).append(CRLF); - mBmsg.append(BMSG_TYPE).append(bmsg.mBmsgType).append(CRLF); - mBmsg.append(BMSG_FOLDER).append(bmsg.mBmsgFolder).append(CRLF); - - for (VCardEntry vcard : bmsg.mOriginators) { - buildVcard(vcard); - } - - { - mBmsg.append(BENV_BEGIN).append(CRLF); - - for (VCardEntry vcard : bmsg.mRecipients) { - buildVcard(vcard); - } - - { - mBmsg.append(BBODY_BEGIN).append(CRLF); - - if (bmsg.mBbodyEncoding != null) { - mBmsg.append(BBODY_ENCODING).append(bmsg.mBbodyEncoding).append(CRLF); - } - - if (bmsg.mBbodyCharset != null) { - mBmsg.append(BBODY_CHARSET).append(bmsg.mBbodyCharset).append(CRLF); - } - - if (bmsg.mBbodyLanguage != null) { - mBmsg.append(BBODY_LANGUAGE).append(bmsg.mBbodyLanguage).append(CRLF); - } - - mBmsg.append(BBODY_LENGTH).append(bodyLen).append(CRLF); - - { - mBmsg.append(MSG_BEGIN).append(CRLF); - - mBmsg.append(bmsg.mMessage).append(CRLF); - - mBmsg.append(MSG_END).append(CRLF); - } - - mBmsg.append(BBODY_END).append(CRLF); - } - - mBmsg.append(BENV_END).append(CRLF); - } - - mBmsg.append(BMSG_END).append(CRLF); - } - - private void buildVcard(VCardEntry vcard) { - String n = buildVcardN(vcard); - List<PhoneData> tel = vcard.getPhoneList(); - List<EmailData> email = vcard.getEmailList(); - - mBmsg.append(VCARD_BEGIN).append(CRLF); - - mBmsg.append(VCARD_VERSION).append(CRLF); - - mBmsg.append(VCARD_N).append(n).append(CRLF); - - if (tel != null && tel.size() > 0) { - mBmsg.append(VCARD_TEL).append(tel.get(0).getNumber()).append(CRLF); - } - - if (email != null && email.size() > 0) { - mBmsg.append(VCARD_EMAIL).append(email.get(0).getAddress()).append(CRLF); - } - - mBmsg.append(VCARD_END).append(CRLF); - } - - private String buildVcardN(VCardEntry vcard) { - NameData nd = vcard.getNameData(); - StringBuilder sb = new StringBuilder(); - - sb.append(nd.getFamily()).append(";"); - sb.append(nd.getGiven() == null ? "" : nd.getGiven()).append(";"); - sb.append(nd.getMiddle() == null ? "" : nd.getMiddle()).append(";"); - sb.append(nd.getPrefix() == null ? "" : nd.getPrefix()).append(";"); - sb.append(nd.getSuffix() == null ? "" : nd.getSuffix()); - - return sb.toString(); - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMapBmessageParser.java b/src/android/bluetooth/client/map/BluetoothMapBmessageParser.java deleted file mode 100644 index ea9bc7f..0000000 --- a/src/android/bluetooth/client/map/BluetoothMapBmessageParser.java +++ /dev/null @@ -1,459 +0,0 @@ -/* - * 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 com.android.vcard.VCardEntry; -import com.android.vcard.VCardEntryConstructor; -import com.android.vcard.VCardEntryHandler; -import com.android.vcard.VCardParser; -import com.android.vcard.VCardParser_V21; -import com.android.vcard.VCardParser_V30; -import com.android.vcard.exception.VCardException; -import com.android.vcard.exception.VCardVersionException; -import android.bluetooth.client.map.BluetoothMapBmessage.Status; -import android.bluetooth.client.map.BluetoothMapBmessage.Type; -import android.bluetooth.client.map.utils.BmsgTokenizer; -import android.bluetooth.client.map.utils.BmsgTokenizer.Property; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.text.ParseException; - -class BluetoothMapBmessageParser { - - private final static String TAG = "BluetoothMapBmessageParser"; - private final static boolean DBG = false; - - private final static String CRLF = "\r\n"; - - private final static Property BEGIN_BMSG = new Property("BEGIN", "BMSG"); - private final static Property END_BMSG = new Property("END", "BMSG"); - - private final static Property BEGIN_VCARD = new Property("BEGIN", "VCARD"); - private final static Property END_VCARD = new Property("END", "VCARD"); - - private final static Property BEGIN_BENV = new Property("BEGIN", "BENV"); - private final static Property END_BENV = new Property("END", "BENV"); - - private final static Property BEGIN_BBODY = new Property("BEGIN", "BBODY"); - private final static Property END_BBODY = new Property("END", "BBODY"); - - private final static Property BEGIN_MSG = new Property("BEGIN", "MSG"); - private final static Property END_MSG = new Property("END", "MSG"); - - private final static int CRLF_LEN = 2; - - /* - * length of "container" for 'message' in bmessage-body-content: - * BEGIN:MSG<CRLF> + <CRLF> + END:MSG<CRFL> - */ - private final static int MSG_CONTAINER_LEN = 22; - - private BmsgTokenizer mParser; - - private final BluetoothMapBmessage mBmsg; - - private BluetoothMapBmessageParser() { - mBmsg = new BluetoothMapBmessage(); - } - - static public BluetoothMapBmessage createBmessage(String str) { - BluetoothMapBmessageParser p = new BluetoothMapBmessageParser(); - - if (DBG) { - Log.d(TAG, "actual wired contents: " + str); - } - - try { - p.parse(str); - } catch (IOException e) { - Log.e(TAG, "I/O exception when parsing bMessage", e); - return null; - } catch (ParseException e) { - Log.e(TAG, "Cannot parse bMessage", e); - return null; - } - - return p.mBmsg; - } - - private ParseException expected(Property... props) { - boolean first = true; - StringBuilder sb = new StringBuilder(); - - for (Property prop : props) { - if (!first) { - sb.append(" or "); - } - sb.append(prop); - first = false; - } - - return new ParseException("Expected: " + sb.toString(), mParser.pos()); - } - - private void parse(String str) throws IOException, ParseException { - - Property prop; - - /* - * <bmessage-object>::= { "BEGIN:BMSG" <CRLF> <bmessage-property> - * [<bmessage-originator>]* <bmessage-envelope> "END:BMSG" <CRLF> } - */ - - mParser = new BmsgTokenizer(str + CRLF); - - prop = mParser.next(); - if (!prop.equals(BEGIN_BMSG)) { - throw expected(BEGIN_BMSG); - } - - prop = parseProperties(); - - while (prop.equals(BEGIN_VCARD)) { - - /* <bmessage-originator>::= <vcard> <CRLF> */ - - StringBuilder vcard = new StringBuilder(); - prop = extractVcard(vcard); - - VCardEntry entry = parseVcard(vcard.toString()); - mBmsg.mOriginators.add(entry); - } - - if (!prop.equals(BEGIN_BENV)) { - throw expected(BEGIN_BENV); - } - - prop = parseEnvelope(1); - - if (!prop.equals(END_BMSG)) { - throw expected(END_BENV); - } - - /* - * there should be no meaningful data left in stream here so we just - * ignore whatever is left - */ - - mParser = null; - } - - private Property parseProperties() throws ParseException { - - Property prop; - - /* - * <bmessage-property>::=<bmessage-version-property> - * <bmessage-readstatus-property> <bmessage-type-property> - * <bmessage-folder-property> <bmessage-version-property>::="VERSION:" - * <common-digit>*"."<common-digit>* <CRLF> - * <bmessage-readstatus-property>::="STATUS:" 'readstatus' <CRLF> - * <bmessage-type-property>::="TYPE:" 'type' <CRLF> - * <bmessage-folder-property>::="FOLDER:" 'foldername' <CRLF> - */ - - do { - prop = mParser.next(); - - if (prop.name.equals("VERSION")) { - mBmsg.mBmsgVersion = prop.value; - - } else if (prop.name.equals("STATUS")) { - for (Status s : Status.values()) { - if (prop.value.equals(s.toString())) { - mBmsg.mBmsgStatus = s; - break; - } - } - - } else if (prop.name.equals("TYPE")) { - for (Type t : Type.values()) { - if (prop.value.equals(t.toString())) { - mBmsg.mBmsgType = t; - break; - } - } - - } else if (prop.name.equals("FOLDER")) { - mBmsg.mBmsgFolder = prop.value; - - } - - } while (!prop.equals(BEGIN_VCARD) && !prop.equals(BEGIN_BENV)); - - return prop; - } - - private Property parseEnvelope(int level) throws IOException, ParseException { - - Property prop; - - /* - * we can support as many nesting level as we want, but MAP spec clearly - * defines that there should be no more than 3 levels. so we verify it - * here. - */ - - if (level > 3) { - throw new ParseException("bEnvelope is nested more than 3 times", mParser.pos()); - } - - /* - * <bmessage-envelope> ::= { "BEGIN:BENV" <CRLF> [<bmessage-recipient>]* - * <bmessage-envelope> | <bmessage-content> "END:BENV" <CRLF> } - */ - - prop = mParser.next(); - - while (prop.equals(BEGIN_VCARD)) { - - /* <bmessage-originator>::= <vcard> <CRLF> */ - - StringBuilder vcard = new StringBuilder(); - prop = extractVcard(vcard); - - if (level == 1) { - VCardEntry entry = parseVcard(vcard.toString()); - mBmsg.mRecipients.add(entry); - } - } - - if (prop.equals(BEGIN_BENV)) { - prop = parseEnvelope(level + 1); - - } else if (prop.equals(BEGIN_BBODY)) { - prop = parseBody(); - - } else { - throw expected(BEGIN_BENV, BEGIN_BBODY); - } - - if (!prop.equals(END_BENV)) { - throw expected(END_BENV); - } - - return mParser.next(); - } - - private Property parseBody() throws IOException, ParseException { - - Property prop; - - /* - * <bmessage-content>::= { "BEGIN:BBODY"<CRLF> [<bmessage-body-part-ID> - * <CRLF>] <bmessage-body-property> <bmessage-body-content>* <CRLF> - * "END:BBODY"<CRLF> } <bmessage-body-part-ID>::="PARTID:" 'Part-ID' - * <bmessage-body-property>::=[<bmessage-body-encoding-property>] - * [<bmessage-body-charset-property>] - * [<bmessage-body-language-property>] - * <bmessage-body-content-length-property> - * <bmessage-body-encoding-property>::="ENCODING:"'encoding' <CRLF> - * <bmessage-body-charset-property>::="CHARSET:"'charset' <CRLF> - * <bmessage-body-language-property>::="LANGUAGE:"'language' <CRLF> - * <bmessage-body-content-length-property>::= "LENGTH:" <common-digit>* - * <CRLF> - */ - - do { - prop = mParser.next(); - - if (prop.name.equals("PARTID")) { - } else if (prop.name.equals("ENCODING")) { - mBmsg.mBbodyEncoding = prop.value; - - } else if (prop.name.equals("CHARSET")) { - mBmsg.mBbodyCharset = prop.value; - - } else if (prop.name.equals("LANGUAGE")) { - mBmsg.mBbodyLanguage = prop.value; - - } else if (prop.name.equals("LENGTH")) { - try { - mBmsg.mBbodyLength = Integer.parseInt(prop.value); - } catch (NumberFormatException e) { - throw new ParseException("Invalid LENGTH value", mParser.pos()); - } - - } - - } while (!prop.equals(BEGIN_MSG)); - - /* - * check that the charset is always set to UTF-8. We expect only text transfer (in lieu with - * the MAPv12 specifying only RFC2822 (text only) for MMS/EMAIL and SMS do not support - * non-text content. If the charset is not set to UTF-8, it is safe to set the message as - * empty. We force the getMessage (see BluetoothMasClient) to only call getMessage with - * UTF-8 as the MCE is not obliged to support native charset. - */ - if (!mBmsg.mBbodyCharset.equals("UTF-8")) { - Log.e(TAG, "The charset was not set to charset UTF-8: " + mBmsg.mBbodyCharset); - } - - /* - * <bmessage-body-content>::={ "BEGIN:MSG"<CRLF> 'message'<CRLF> - * "END:MSG"<CRLF> } - */ - - int messageLen = mBmsg.mBbodyLength - MSG_CONTAINER_LEN; - int offset = messageLen + CRLF_LEN; - int restartPos = mParser.pos() + offset; - - /* - * length is specified in bytes so we need to convert from unicode - * string back to bytes array - */ - - String remng = mParser.remaining(); - byte[] data = remng.getBytes(); - - /* restart parsing from after 'message'<CRLF> */ - mParser = new BmsgTokenizer(new String(data, offset, data.length - offset), restartPos); - - prop = mParser.next(true); - - if (prop != null) { - if (prop.equals(END_MSG)) { - if (mBmsg.mBbodyCharset.equals("UTF-8")) { - mBmsg.mMessage = new String(data, 0, messageLen, StandardCharsets.UTF_8); - } else { - mBmsg.mMessage = null; - } - } else { - /* Handle possible exception for incorrect LENGTH value - * from MSE while parsing GET Message response */ - Log.e(TAG, "Prop Invalid: "+ prop.toString()); - Log.e(TAG, "Possible Invalid LENGTH value"); - throw expected(END_MSG); - } - } else { - - data = null; - - /* - * now we check if bMessage can be parsed if LENGTH is handled as - * number of characters instead of number of bytes - */ - if (offset < 0 || offset > remng.length()) { - /* Handle possible exception for incorrect LENGTH value - * from MSE while parsing GET Message response */ - throw new ParseException("Invalid LENGTH value", mParser.pos()); - } - - Log.w(TAG, "byte LENGTH seems to be invalid, trying with char length"); - - mParser = new BmsgTokenizer(remng.substring(offset)); - - prop = mParser.next(); - - if (!prop.equals(END_MSG)) { - throw expected(END_MSG); - } - - if (mBmsg.mBbodyCharset.equals("UTF-8")) { - mBmsg.mMessage = remng.substring(0, messageLen); - } else { - mBmsg.mMessage = null; - } - } - - prop = mParser.next(); - - if (!prop.equals(END_BBODY)) { - throw expected(END_BBODY); - } - - return mParser.next(); - } - - private Property extractVcard(StringBuilder out) throws IOException, ParseException { - Property prop; - - out.append(BEGIN_VCARD).append(CRLF); - - do { - prop = mParser.next(); - out.append(prop).append(CRLF); - } while (!prop.equals(END_VCARD)); - - return mParser.next(); - } - - private class VcardHandler implements VCardEntryHandler { - - VCardEntry vcard; - - @Override - public void onStart() { - } - - @Override - public void onEntryCreated(VCardEntry entry) { - vcard = entry; - } - - @Override - public void onEnd() { - } - }; - - private VCardEntry parseVcard(String str) throws IOException, ParseException { - VCardEntry vcard = null; - - try { - VCardParser p = new VCardParser_V21(); - VCardEntryConstructor c = new VCardEntryConstructor(); - VcardHandler handler = new VcardHandler(); - c.addEntryHandler(handler); - p.addInterpreter(c); - p.parse(new ByteArrayInputStream(str.getBytes())); - - vcard = handler.vcard; - - } catch (VCardVersionException e1) { - - try { - VCardParser p = new VCardParser_V30(); - VCardEntryConstructor c = new VCardEntryConstructor(); - VcardHandler handler = new VcardHandler(); - c.addEntryHandler(handler); - p.addInterpreter(c); - p.parse(new ByteArrayInputStream(str.getBytes())); - - vcard = handler.vcard; - - } catch (VCardVersionException e2) { - // will throw below - } catch (VCardException e2) { - // will throw below - } - - } catch (VCardException e1) { - // will throw below - } - - if (vcard == null) { - throw new ParseException("Cannot parse vCard object (neither 2.1 nor 3.0?)", - mParser.pos()); - } - - return vcard; - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMapEventReport.java b/src/android/bluetooth/client/map/BluetoothMapEventReport.java deleted file mode 100644 index 5963db4..0000000 --- a/src/android/bluetooth/client/map/BluetoothMapEventReport.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * 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; - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMapFolderListing.java b/src/android/bluetooth/client/map/BluetoothMapFolderListing.java deleted file mode 100644 index f0494b3..0000000 --- a/src/android/bluetooth/client/map/BluetoothMapFolderListing.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlPullParserFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; - -class BluetoothMapFolderListing { - - private static final String TAG = "BluetoothMasFolderListing"; - - private final ArrayList<String> mFolders; - - public BluetoothMapFolderListing(InputStream in) { - mFolders = new ArrayList<String>(); - - parse(in); - } - - public void parse(InputStream in) { - - 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("folder")) { - mFolders.add(xpp.getAttributeValue(null, "name")); - } - 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); - } - } - - public ArrayList<String> getList() { - return mFolders; - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMapMessage.java b/src/android/bluetooth/client/map/BluetoothMapMessage.java deleted file mode 100644 index 5ce6c4b..0000000 --- a/src/android/bluetooth/client/map/BluetoothMapMessage.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * 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.bluetooth.client.map.utils.ObexTime; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.math.BigInteger; -import java.util.Date; -import java.util.HashMap; - -/** - * Object representation of message received in messages listing - * <p> - * This object will be received in - * {@link BluetoothMasClient#EVENT_GET_MESSAGES_LISTING} callback message. - */ -public class BluetoothMapMessage { - - private final String mHandle; - - private final String mSubject; - - private final Date mDateTime; - - private final String mSenderName; - - private final String mSenderAddressing; - - private final String mReplytoAddressing; - - private final String mRecipientName; - - private final String mRecipientAddressing; - - private final Type mType; - - private final int mSize; - - private final boolean mText; - - private final ReceptionStatus mReceptionStatus; - - private final int mAttachmentSize; - - private final boolean mPriority; - - private final boolean mRead; - - private final boolean mSent; - - private final boolean mProtected; - - public enum Type { - UNKNOWN, EMAIL, SMS_GSM, SMS_CDMA, MMS - }; - - public enum ReceptionStatus { - UNKNOWN, COMPLETE, FRACTIONED, NOTIFICATION - } - - BluetoothMapMessage(HashMap<String, String> attrs) throws IllegalArgumentException { - int size; - - try { - /* just to validate */ - new BigInteger(attrs.get("handle"), 16); - - mHandle = attrs.get("handle"); - } catch (NumberFormatException e) { - /* - * handle MUST have proper value, if it does not then throw - * something here - */ - throw new IllegalArgumentException(e); - } - - mSubject = attrs.get("subject"); - String dateTime = attrs.get("datetime"); - //Handle possible NPE when not able to retreive datetime attribute - if(dateTime != null){ - mDateTime = (new ObexTime(dateTime)).getTime(); - } else { - mDateTime = null; - } - - - mSenderName = attrs.get("sender_name"); - - mSenderAddressing = attrs.get("sender_addressing"); - - mReplytoAddressing = attrs.get("replyto_addressing"); - - mRecipientName = attrs.get("recipient_name"); - - mRecipientAddressing = attrs.get("recipient_addressing"); - - mType = strToType(attrs.get("type")); - - try { - size = Integer.parseInt(attrs.get("size")); - } catch (NumberFormatException e) { - size = 0; - } - - mSize = size; - - mText = yesnoToBoolean(attrs.get("text")); - - mReceptionStatus = strToReceptionStatus(attrs.get("reception_status")); - - try { - size = Integer.parseInt(attrs.get("attachment_size")); - } catch (NumberFormatException e) { - size = 0; - } - - mAttachmentSize = size; - - mPriority = yesnoToBoolean(attrs.get("priority")); - - mRead = yesnoToBoolean(attrs.get("read")); - - mSent = yesnoToBoolean(attrs.get("sent")); - - mProtected = yesnoToBoolean(attrs.get("protected")); - } - - private boolean yesnoToBoolean(String yesno) { - return "yes".equals(yesno); - } - - private Type strToType(String s) { - if ("EMAIL".equals(s)) { - return Type.EMAIL; - } else if ("SMS_GSM".equals(s)) { - return Type.SMS_GSM; - } else if ("SMS_CDMA".equals(s)) { - return Type.SMS_CDMA; - } else if ("MMS".equals(s)) { - return Type.MMS; - } - - return Type.UNKNOWN; - } - - private ReceptionStatus strToReceptionStatus(String s) { - if ("complete".equals(s)) { - return ReceptionStatus.COMPLETE; - } else if ("fractioned".equals(s)) { - return ReceptionStatus.FRACTIONED; - } else if ("notification".equals(s)) { - return ReceptionStatus.NOTIFICATION; - } - - return ReceptionStatus.UNKNOWN; - } - - @Override - public String toString() { - JSONObject json = new JSONObject(); - - try { - json.put("handle", mHandle); - json.put("subject", mSubject); - json.put("datetime", mDateTime); - json.put("sender_name", mSenderName); - json.put("sender_addressing", mSenderAddressing); - json.put("replyto_addressing", mReplytoAddressing); - json.put("recipient_name", mRecipientName); - json.put("recipient_addressing", mRecipientAddressing); - json.put("type", mType); - json.put("size", mSize); - json.put("text", mText); - json.put("reception_status", mReceptionStatus); - json.put("attachment_size", mAttachmentSize); - json.put("priority", mPriority); - json.put("read", mRead); - json.put("sent", mSent); - json.put("protected", mProtected); - } catch (JSONException e) { - // do nothing - } - - return json.toString(); - } - - /** - * @return value corresponding to <code>handle</code> parameter in MAP - * specification - */ - public String getHandle() { - return mHandle; - } - - /** - * @return value corresponding to <code>subject</code> parameter in MAP - * specification - */ - public String getSubject() { - return mSubject; - } - - /** - * @return <code>Date</code> object corresponding to <code>datetime</code> - * parameter in MAP specification - */ - public Date getDateTime() { - return mDateTime; - } - - /** - * @return value corresponding to <code>sender_name</code> parameter in MAP - * specification - */ - public String getSenderName() { - return mSenderName; - } - - /** - * @return value corresponding to <code>sender_addressing</code> parameter - * in MAP specification - */ - public String getSenderAddressing() { - return mSenderAddressing; - } - - /** - * @return value corresponding to <code>replyto_addressing</code> parameter - * in MAP specification - */ - public String getReplytoAddressing() { - return mReplytoAddressing; - } - - /** - * @return value corresponding to <code>recipient_name</code> parameter in - * MAP specification - */ - public String getRecipientName() { - return mRecipientName; - } - - /** - * @return value corresponding to <code>recipient_addressing</code> - * parameter in MAP specification - */ - public String getRecipientAddressing() { - return mRecipientAddressing; - } - - /** - * @return {@link Type} object corresponding to <code>type</code> parameter - * in MAP specification - */ - public Type getType() { - return mType; - } - - /** - * @return value corresponding to <code>size</code> parameter in MAP - * specification - */ - public int getSize() { - return mSize; - } - - /** - * @return {@link .ReceptionStatus} object corresponding to - * <code>reception_status</code> parameter in MAP specification - */ - public ReceptionStatus getReceptionStatus() { - return mReceptionStatus; - } - - /** - * @return value corresponding to <code>attachment_size</code> parameter in - * MAP specification - */ - public int getAttachmentSize() { - return mAttachmentSize; - } - - /** - * @return value corresponding to <code>text</code> parameter in MAP - * specification - */ - public boolean isText() { - return mText; - } - - /** - * @return value corresponding to <code>priority</code> parameter in MAP - * specification - */ - public boolean isPriority() { - return mPriority; - } - - /** - * @return value corresponding to <code>read</code> parameter in MAP - * specification - */ - public boolean isRead() { - return mRead; - } - - /** - * @return value corresponding to <code>sent</code> parameter in MAP - * specification - */ - public boolean isSent() { - return mSent; - } - - /** - * @return value corresponding to <code>protected</code> parameter in MAP - * specification - */ - public boolean isProtected() { - return mProtected; - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMapMessagesListing.java b/src/android/bluetooth/client/map/BluetoothMapMessagesListing.java deleted file mode 100644 index 2fb3dea..0000000 --- a/src/android/bluetooth/client/map/BluetoothMapMessagesListing.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlPullParserFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; - -class BluetoothMapMessagesListing { - - private static final String TAG = "BluetoothMapMessagesListing"; - - private final ArrayList<BluetoothMapMessage> mMessages; - - public BluetoothMapMessagesListing(InputStream in) { - mMessages = new ArrayList<BluetoothMapMessage>(); - - parse(in); - } - - public void parse(InputStream in) { - - 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("msg")) { - - HashMap<String, String> attrs = new HashMap<String, String>(); - - for (int i = 0; i < xpp.getAttributeCount(); i++) { - attrs.put(xpp.getAttributeName(i), xpp.getAttributeValue(i)); - } - - try { - BluetoothMapMessage msg = new BluetoothMapMessage(attrs); - mMessages.add(msg); - } catch (IllegalArgumentException e) { - /* TODO: provide something more useful here */ - Log.w(TAG, "Invalid <msg/>"); - } - } - 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); - } - } - - public ArrayList<BluetoothMapMessage> getList() { - return mMessages; - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMapRfcommTransport.java b/src/android/bluetooth/client/map/BluetoothMapRfcommTransport.java deleted file mode 100644 index 5bec982..0000000 --- a/src/android/bluetooth/client/map/BluetoothMapRfcommTransport.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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.bluetooth.BluetoothSocket; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import javax.obex.ObexTransport; - -class BluetoothMapRfcommTransport implements ObexTransport { - private final BluetoothSocket mSocket; - - public BluetoothMapRfcommTransport(BluetoothSocket socket) { - super(); - mSocket = socket; - } - - @Override - public void create() throws IOException { - } - - @Override - public void listen() throws IOException { - } - - @Override - public void close() throws IOException { - mSocket.close(); - } - - @Override - public void connect() throws IOException { - } - - @Override - public void disconnect() throws IOException { - } - - @Override - public InputStream openInputStream() throws IOException { - return mSocket.getInputStream(); - } - - @Override - public OutputStream openOutputStream() throws IOException { - return mSocket.getOutputStream(); - } - - @Override - public DataInputStream openDataInputStream() throws IOException { - return new DataInputStream(openInputStream()); - } - - @Override - public DataOutputStream openDataOutputStream() throws IOException { - return new DataOutputStream(openOutputStream()); - } - - @Override - public int getMaxTransmitPacketSize() { - return -1; - } - - @Override - public int getMaxReceivePacketSize() { - return -1; - } - - @Override - public boolean isSrmSupported() { - return false; - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMasClient.java b/src/android/bluetooth/client/map/BluetoothMasClient.java deleted file mode 100644 index 87f5a38..0000000 --- a/src/android/bluetooth/client/map/BluetoothMasClient.java +++ /dev/null @@ -1,1106 +0,0 @@ -/* - * 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.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothMasInstance; -import android.bluetooth.BluetoothSocket; -import android.bluetooth.SdpMasRecord; -import android.os.Handler; -import android.os.Message; -import android.util.Log; - -import android.bluetooth.client.map.BluetoothMasRequestSetMessageStatus.StatusIndicator; -import android.bluetooth.client.map.utils.ObexTime; - -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.math.BigInteger; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Date; -import java.util.Iterator; - -import javax.obex.ObexTransport; - -public class BluetoothMasClient { - - private final static String TAG = "BluetoothMasClient"; - - private static final int SOCKET_CONNECTED = 10; - - private static final int SOCKET_ERROR = 11; - - /** - * Callback message sent when connection state changes - * <p> - * <code>arg1</code> is set to {@link #STATUS_OK} when connection is - * established successfully and {@link #STATUS_FAILED} when connection - * either failed or was disconnected (depends on request from application) - * - * @see #connect() - * @see #disconnect() - */ - public static final int EVENT_CONNECT = 1; - - /** - * Callback message sent when MSE accepted update inbox request - * - * @see #updateInbox() - */ - public static final int EVENT_UPDATE_INBOX = 2; - - /** - * Callback message sent when path is changed - * <p> - * <code>obj</code> is set to path currently set on MSE - * - * @see #setFolderRoot() - * @see #setFolderUp() - * @see #setFolderDown(String) - */ - public static final int EVENT_SET_PATH = 3; - - /** - * Callback message sent when folder listing is received - * <p> - * <code>obj</code> contains ArrayList of sub-folder names - * - * @see #getFolderListing() - * @see #getFolderListing(int, int) - */ - public static final int EVENT_GET_FOLDER_LISTING = 4; - - /** - * Callback message sent when folder listing size is received - * <p> - * <code>obj</code> contains number of items in folder listing - * - * @see #getFolderListingSize() - */ - public static final int EVENT_GET_FOLDER_LISTING_SIZE = 5; - - /** - * Callback message sent when messages listing is received - * <p> - * <code>obj</code> contains ArrayList of {@link BluetoothMapBmessage} - * - * @see #getMessagesListing(String, int) - * @see #getMessagesListing(String, int, MessagesFilter, int) - * @see #getMessagesListing(String, int, MessagesFilter, int, int, int) - */ - public static final int EVENT_GET_MESSAGES_LISTING = 6; - - /** - * Callback message sent when message is received - * <p> - * <code>obj</code> contains {@link BluetoothMapBmessage} - * - * @see #getMessage(String, CharsetType, boolean) - */ - public static final int EVENT_GET_MESSAGE = 7; - - /** - * Callback message sent when message status is changed - * - * @see #setMessageDeletedStatus(String, boolean) - * @see #setMessageReadStatus(String, boolean) - */ - public static final int EVENT_SET_MESSAGE_STATUS = 8; - - /** - * Callback message sent when message is pushed to MSE - * <p> - * <code>obj</code> contains handle of message as allocated by MSE - * - * @see #pushMessage(String, BluetoothMapBmessage, CharsetType) - * @see #pushMessage(String, BluetoothMapBmessage, CharsetType, boolean, - * boolean) - */ - public static final int EVENT_PUSH_MESSAGE = 9; - - /** - * Callback message sent when notification status is changed - * <p> - * <code>obj</code> contains <code>1</code> if notifications are enabled and - * <code>0</code> otherwise - * - * @see #setNotificationRegistration(boolean) - */ - public static final int EVENT_SET_NOTIFICATION_REGISTRATION = 10; - - /** - * Callback message sent when event report is received from MSE to MNS - * <p> - * <code>obj</code> contains {@link BluetoothMapEventReport} - * - * @see #setNotificationRegistration(boolean) - */ - public static final int EVENT_EVENT_REPORT = 11; - - /** - * Callback message sent when messages listing size is received - * <p> - * <code>obj</code> contains number of items in messages listing - * - * @see #getMessagesListingSize() - */ - public static final int EVENT_GET_MESSAGES_LISTING_SIZE = 12; - - /** - * Status for callback message when request is successful - */ - public static final int STATUS_OK = 0; - - /** - * Status for callback message when request is not successful - */ - public static final int STATUS_FAILED = 1; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_DEFAULT = 0x00000000; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_SUBJECT = 0x00000001; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_DATETIME = 0x00000002; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_SENDER_NAME = 0x00000004; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_SENDER_ADDRESSING = 0x00000008; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_RECIPIENT_NAME = 0x00000010; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_RECIPIENT_ADDRESSING = 0x00000020; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_TYPE = 0x00000040; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_SIZE = 0x00000080; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_RECEPTION_STATUS = 0x00000100; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_TEXT = 0x00000200; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_ATTACHMENT_SIZE = 0x00000400; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_PRIORITY = 0x00000800; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_READ = 0x00001000; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_SENT = 0x00002000; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_PROTECTED = 0x00004000; - - /** - * Constant corresponding to <code>ParameterMask</code> application - * parameter value in MAP specification - */ - public static final int PARAMETER_REPLYTO_ADDRESSING = 0x00008000; - - public enum ConnectionState { - DISCONNECTED, CONNECTING, CONNECTED, DISCONNECTING; - } - - public enum CharsetType { - NATIVE, UTF_8; - } - - /** device associated with client */ - private final BluetoothDevice mDevice; - - /** MAS instance associated with client */ - private final SdpMasRecord mMas; - - /** callback handler to application */ - private final Handler mCallback; - - private ConnectionState mConnectionState = ConnectionState.DISCONNECTED; - - private boolean mNotificationEnabled = false; - - private SocketConnectThread mConnectThread = null; - - private ObexTransport mObexTransport = null; - - private BluetoothMasObexClientSession mObexSession = null; - - private SessionHandler mSessionHandler = null; - - private BluetoothMnsService mMnsService = null; - - private ArrayDeque<String> mPath = null; - - private static class SessionHandler extends Handler { - - private final WeakReference<BluetoothMasClient> mClient; - - public SessionHandler(BluetoothMasClient client) { - super(); - - mClient = new WeakReference<BluetoothMasClient>(client); - } - - @Override - public void handleMessage(Message msg) { - - BluetoothMasClient client = mClient.get(); - if (client == null) { - return; - } - Log.v(TAG, "handleMessage "+msg.what); - - switch (msg.what) { - case SOCKET_ERROR: - client.mConnectThread = null; - client.sendToClient(EVENT_CONNECT, false); - break; - - case SOCKET_CONNECTED: - client.mConnectThread = null; - - client.mObexTransport = (ObexTransport) msg.obj; - - client.mObexSession = new BluetoothMasObexClientSession(client.mObexTransport, - client.mSessionHandler); - client.mObexSession.start(); - break; - - case BluetoothMasObexClientSession.MSG_OBEX_CONNECTED: - client.mPath.clear(); // we're in root after connected - client.mConnectionState = ConnectionState.CONNECTED; - client.sendToClient(EVENT_CONNECT, true); - break; - - case BluetoothMasObexClientSession.MSG_OBEX_DISCONNECTED: - client.mConnectionState = ConnectionState.DISCONNECTED; - client.mNotificationEnabled = false; - client.mObexSession = null; - client.sendToClient(EVENT_CONNECT, false); - break; - - case BluetoothMasObexClientSession.MSG_REQUEST_COMPLETED: - BluetoothMasRequest request = (BluetoothMasRequest) msg.obj; - int status = request.isSuccess() ? STATUS_OK : STATUS_FAILED; - - Log.v(TAG, "MSG_REQUEST_COMPLETED (" + status + ") for " - + request.getClass().getName()); - - if (request instanceof BluetoothMasRequestUpdateInbox) { - client.sendToClient(EVENT_UPDATE_INBOX, request.isSuccess()); - - } else if (request instanceof BluetoothMasRequestSetPath) { - if (request.isSuccess()) { - BluetoothMasRequestSetPath req = (BluetoothMasRequestSetPath) request; - switch (req.mDir) { - case UP: - if (client.mPath.size() > 0) { - client.mPath.removeLast(); - } - break; - - case ROOT: - client.mPath.clear(); - break; - - case DOWN: - client.mPath.addLast(req.mName); - break; - } - } - - client.sendToClient(EVENT_SET_PATH, request.isSuccess(), - client.getCurrentPath()); - - } else if (request instanceof BluetoothMasRequestGetFolderListing) { - BluetoothMasRequestGetFolderListing req = (BluetoothMasRequestGetFolderListing) request; - ArrayList<String> folders = req.getList(); - - client.sendToClient(EVENT_GET_FOLDER_LISTING, request.isSuccess(), folders); - - } else if (request instanceof BluetoothMasRequestGetFolderListingSize) { - int size = ((BluetoothMasRequestGetFolderListingSize) request).getSize(); - - client.sendToClient(EVENT_GET_FOLDER_LISTING_SIZE, request.isSuccess(), - size); - - } else if (request instanceof BluetoothMasRequestGetMessagesListing) { - BluetoothMasRequestGetMessagesListing req = (BluetoothMasRequestGetMessagesListing) request; - ArrayList<BluetoothMapMessage> msgs = req.getList(); - - client.sendToClient(EVENT_GET_MESSAGES_LISTING, request.isSuccess(), msgs); - - } else if (request instanceof BluetoothMasRequestGetMessage) { - BluetoothMasRequestGetMessage req = (BluetoothMasRequestGetMessage) request; - BluetoothMapBmessage bmsg = req.getMessage(); - - client.sendToClient(EVENT_GET_MESSAGE, request.isSuccess(), bmsg); - - } else if (request instanceof BluetoothMasRequestSetMessageStatus) { - client.sendToClient(EVENT_SET_MESSAGE_STATUS, request.isSuccess()); - - } else if (request instanceof BluetoothMasRequestPushMessage) { - BluetoothMasRequestPushMessage req = (BluetoothMasRequestPushMessage) request; - String handle = req.getMsgHandle(); - - client.sendToClient(EVENT_PUSH_MESSAGE, request.isSuccess(), handle); - - } else if (request instanceof BluetoothMasRequestSetNotificationRegistration) { - BluetoothMasRequestSetNotificationRegistration req = (BluetoothMasRequestSetNotificationRegistration) request; - - client.mNotificationEnabled = req.isSuccess() ? req.getStatus() - : client.mNotificationEnabled; - - client.sendToClient(EVENT_SET_NOTIFICATION_REGISTRATION, - request.isSuccess(), - client.mNotificationEnabled ? 1 : 0); - } else if (request instanceof BluetoothMasRequestGetMessagesListingSize) { - int size = ((BluetoothMasRequestGetMessagesListingSize) request).getSize(); - client.sendToClient(EVENT_GET_MESSAGES_LISTING_SIZE, request.isSuccess(), - size); - } - break; - - case BluetoothMnsService.EVENT_REPORT: - /* pass event report directly to app */ - client.sendToClient(EVENT_EVENT_REPORT, true, msg.obj); - break; - } - } - } - - private void sendToClient(int event, boolean success) { - sendToClient(event, success, null); - } - - private void sendToClient(int event, boolean success, int param) { - sendToClient(event, success, Integer.valueOf(param)); - } - - private void sendToClient(int event, boolean success, Object param) { - // Send event, status and notification state for both sucess and failure case. - mCallback.obtainMessage(event, success ? STATUS_OK : STATUS_FAILED, mMas.getMasInstanceId(), - param).sendToTarget(); - } - - private class SocketConnectThread extends Thread { - private BluetoothSocket socket = null; - - public SocketConnectThread() { - super("SocketConnectThread"); - } - - @Override - public void run() { - try { - socket = mDevice.createRfcommSocket(mMas.getRfcommCannelNumber()); - socket.connect(); - - BluetoothMapRfcommTransport transport; - transport = new BluetoothMapRfcommTransport(socket); - - mSessionHandler.obtainMessage(SOCKET_CONNECTED, transport).sendToTarget(); - } catch (IOException e) { - Log.e(TAG, "Error when creating/connecting socket", e); - - closeSocket(); - mSessionHandler.obtainMessage(SOCKET_ERROR).sendToTarget(); - } - } - - @Override - public void interrupt() { - closeSocket(); - } - - private void closeSocket() { - try { - if (socket != null) { - socket.close(); - } - } catch (IOException e) { - Log.e(TAG, "Error when closing socket", e); - } - } - } - - /** - * Object representation of filters to be applied on message listing - * - * @see #getMessagesListing(String, int, MessagesFilter, int) - * @see #getMessagesListing(String, int, MessagesFilter, int, int, int) - */ - public static final class MessagesFilter { - - public final static byte MESSAGE_TYPE_ALL = 0x00; - public final static byte MESSAGE_TYPE_SMS_GSM = 0x01; - public final static byte MESSAGE_TYPE_SMS_CDMA = 0x02; - public final static byte MESSAGE_TYPE_EMAIL = 0x04; - public final static byte MESSAGE_TYPE_MMS = 0x08; - - public final static byte READ_STATUS_ANY = 0x00; - public final static byte READ_STATUS_UNREAD = 0x01; - public final static byte READ_STATUS_READ = 0x02; - - public final static byte PRIORITY_ANY = 0x00; - public final static byte PRIORITY_HIGH = 0x01; - public final static byte PRIORITY_NON_HIGH = 0x02; - - byte messageType = MESSAGE_TYPE_ALL; - - String periodBegin = null; - - String periodEnd = null; - - byte readStatus = READ_STATUS_ANY; - - String recipient = null; - - String originator = null; - - byte priority = PRIORITY_ANY; - - public MessagesFilter() { - } - - public void setMessageType(byte filter) { - messageType = filter; - } - - public void setPeriod(Date filterBegin, Date filterEnd) { - //Handle possible NPE for obexTime constructor utility - if(filterBegin != null ) - periodBegin = (new ObexTime(filterBegin)).toString(); - if(filterEnd != null) - periodEnd = (new ObexTime(filterEnd)).toString(); - } - - public void setReadStatus(byte readfilter) { - readStatus = readfilter; - } - - public void setRecipient(String filter) { - if ("".equals(filter)) { - recipient = null; - } else { - recipient = filter; - } - } - - public void setOriginator(String filter) { - if ("".equals(filter)) { - originator = null; - } else { - originator = filter; - } - } - - public void setPriority(byte filter) { - priority = filter; - } - } - - /** - * Constructs client object to communicate with single MAS instance on MSE - * - * @param device {@link BluetoothDevice} corresponding to remote device - * acting as MSE - * @param mas {@link BluetoothMasInstance} object describing MAS instance on - * remote device - * @param callback {@link Handler} object to which callback messages will be - * sent Each message will have <code>arg1</code> set to either - * {@link #STATUS_OK} or {@link #STATUS_FAILED} and - * <code>arg2</code> to MAS instance ID. <code>obj</code> in - * message is event specific. - */ - public BluetoothMasClient(BluetoothDevice device, SdpMasRecord mas, - Handler callback) { - mDevice = device; - mMas = mas; - mCallback = callback; - - mPath = new ArrayDeque<String>(); - } - - /** - * Retrieves MAS instance data associated with client - * - * @return instance data object - */ - public SdpMasRecord getInstanceData() { - return mMas; - } - - /** - * Connects to MAS instance - * <p> - * Upon completion callback handler will receive {@link #EVENT_CONNECT} - */ - public void connect() { - if (mSessionHandler == null) { - mSessionHandler = new SessionHandler(this); - } - - if (mConnectThread == null && mObexSession == null) { - mConnectionState = ConnectionState.CONNECTING; - - mConnectThread = new SocketConnectThread(); - mConnectThread.start(); - } - } - - /** - * Disconnects from MAS instance - * <p> - * Upon completion callback handler will receive {@link #EVENT_CONNECT} - */ - public void disconnect() { - if (mConnectThread == null && mObexSession == null) { - return; - } - - mConnectionState = ConnectionState.DISCONNECTING; - - if (mConnectThread != null) { - mConnectThread.interrupt(); - } - - if (mObexSession != null) { - mObexSession.stop(); - } - } - - @Override - public void finalize() { - disconnect(); - } - - /** - * Gets current connection state - * - * @return current connection state - * @see ConnectionState - */ - public ConnectionState getState() { - return mConnectionState; - } - - private boolean enableNotifications() { - Log.v(TAG, "enableNotifications()"); - - if (mMnsService == null) { - mMnsService = new BluetoothMnsService(); - } - - mMnsService.registerCallback(mMas.getMasInstanceId(), mSessionHandler); - - BluetoothMasRequest request = new BluetoothMasRequestSetNotificationRegistration(true); - return mObexSession.makeRequest(request); - } - - private boolean disableNotifications() { - Log.v(TAG, "enableNotifications()"); - - if (mMnsService != null) { - mMnsService.unregisterCallback(mMas.getMasInstanceId()); - } - - mMnsService = null; - - BluetoothMasRequest request = new BluetoothMasRequestSetNotificationRegistration(false); - return mObexSession.makeRequest(request); - } - - /** - * Sets state of notifications for MAS instance - * <p> - * Once notifications are enabled, callback handler will receive - * {@link #EVENT_EVENT_REPORT} when new notification is received - * <p> - * Upon completion callback handler will receive - * {@link #EVENT_SET_NOTIFICATION_REGISTRATION} - * - * @param status <code>true</code> if notifications shall be enabled, - * <code>false</code> otherwise - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean setNotificationRegistration(boolean status) { - if (mObexSession == null) { - return false; - } - - if (status) { - return enableNotifications(); - } else { - return disableNotifications(); - } - } - - /** - * Gets current state of notifications for MAS instance - * - * @return <code>true</code> if notifications are enabled, - * <code>false</code> otherwise - */ - public boolean getNotificationRegistration() { - return mNotificationEnabled; - } - - /** - * Goes back to root of folder hierarchy - * <p> - * Upon completion callback handler will receive {@link #EVENT_SET_PATH} - * - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean setFolderRoot() { - if (mObexSession == null) { - return false; - } - - BluetoothMasRequest request = new BluetoothMasRequestSetPath(true); - return mObexSession.makeRequest(request); - } - - /** - * Goes back to parent folder in folder hierarchy - * <p> - * Upon completion callback handler will receive {@link #EVENT_SET_PATH} - * - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean setFolderUp() { - if (mObexSession == null) { - return false; - } - - BluetoothMasRequest request = new BluetoothMasRequestSetPath(false); - return mObexSession.makeRequest(request); - } - - /** - * Goes down to specified sub-folder in folder hierarchy - * <p> - * Upon completion callback handler will receive {@link #EVENT_SET_PATH} - * - * @param name name of sub-folder - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean setFolderDown(String name) { - if (mObexSession == null) { - return false; - } - - if (name == null || name.isEmpty() || name.contains("/")) { - return false; - } - - BluetoothMasRequest request = new BluetoothMasRequestSetPath(name); - return mObexSession.makeRequest(request); - } - - /** - * Gets current path in folder hierarchy - * - * @return current path - */ - public String getCurrentPath() { - if (mPath.size() == 0) { - return ""; - } - - Iterator<String> iter = mPath.iterator(); - - StringBuilder sb = new StringBuilder(iter.next()); - - while (iter.hasNext()) { - sb.append("/").append(iter.next()); - } - - return sb.toString(); - } - - /** - * Gets list of sub-folders in current folder - * <p> - * Upon completion callback handler will receive - * {@link #EVENT_GET_FOLDER_LISTING} - * - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean getFolderListing() { - return getFolderListing((short) 0, (short) 0); - } - - /** - * Gets list of sub-folders in current folder - * <p> - * Upon completion callback handler will receive - * {@link #EVENT_GET_FOLDER_LISTING} - * - * @param maxListCount maximum number of items returned or <code>0</code> - * for default value - * @param listStartOffset index of first item returned or <code>0</code> for - * default value - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - * @throws IllegalArgumentException if either maxListCount or - * listStartOffset are outside allowed range [0..65535] - */ - public boolean getFolderListing(int maxListCount, int listStartOffset) { - if (mObexSession == null) { - return false; - } - - BluetoothMasRequest request = new BluetoothMasRequestGetFolderListing(maxListCount, - listStartOffset); - return mObexSession.makeRequest(request); - } - - /** - * Gets number of sub-folders in current folder - * <p> - * Upon completion callback handler will receive - * {@link #EVENT_GET_FOLDER_LISTING_SIZE} - * - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean getFolderListingSize() { - if (mObexSession == null) { - return false; - } - - BluetoothMasRequest request = new BluetoothMasRequestGetFolderListingSize(); - return mObexSession.makeRequest(request); - } - - /** - * Gets list of messages in specified sub-folder - * <p> - * Upon completion callback handler will receive - * {@link #EVENT_GET_MESSAGES_LISTING} - * - * @param folder name of sub-folder or <code>null</code> for current folder - * @param parameters bit-mask specifying requested parameters in listing or - * <code>0</code> for default value - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean getMessagesListing(String folder, int parameters) { - return getMessagesListing(folder, parameters, null, (byte) 0, 0, 0); - } - - /** - * Gets list of messages in specified sub-folder - * <p> - * Upon completion callback handler will receive - * {@link #EVENT_GET_MESSAGES_LISTING} - * - * @param folder name of sub-folder or <code>null</code> for current folder - * @param parameters corresponds to <code>ParameterMask</code> application - * parameter in MAP specification - * @param filter {@link MessagesFilter} object describing filters to be - * applied on listing by MSE - * @param subjectLength maximum length of message subject in returned - * listing or <code>0</code> for default value - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - * @throws IllegalArgumentException if subjectLength is outside allowed - * range [0..255] - */ - public boolean getMessagesListing(String folder, int parameters, MessagesFilter filter, - int subjectLength) { - - return getMessagesListing(folder, parameters, filter, subjectLength, 0, 0); - } - - /** - * Gets list of messages in specified sub-folder - * <p> - * Upon completion callback handler will receive - * {@link #EVENT_GET_MESSAGES_LISTING} - * - * @param folder name of sub-folder or <code>null</code> for current folder - * @param parameters corresponds to <code>ParameterMask</code> application - * parameter in MAP specification - * @param filter {@link MessagesFilter} object describing filters to be - * applied on listing by MSE - * @param subjectLength maximum length of message subject in returned - * listing or <code>0</code> for default value - * @param maxListCount maximum number of items returned or <code>0</code> - * for default value - * @param listStartOffset index of first item returned or <code>0</code> for - * default value - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - * @throws IllegalArgumentException if subjectLength is outside allowed - * range [0..255] or either maxListCount or listStartOffset are - * outside allowed range [0..65535] - */ - public boolean getMessagesListing(String folder, int parameters, MessagesFilter filter, - int subjectLength, int maxListCount, int listStartOffset) { - - if (mObexSession == null) { - return false; - } - - BluetoothMasRequest request = new BluetoothMasRequestGetMessagesListing(folder, - parameters, filter, subjectLength, maxListCount, listStartOffset); - return mObexSession.makeRequest(request); - } - - /** - * Gets number of messages in current folder - * <p> - * Upon completion callback handler will receive - * {@link #EVENT_GET_MESSAGES_LISTING_SIZE} - * - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean getMessagesListingSize() { - if (mObexSession == null) { - return false; - } - - BluetoothMasRequest request = new BluetoothMasRequestGetMessagesListingSize(); - return mObexSession.makeRequest(request); - } - - /** - * Retrieves message from MSE - * <p> - * Upon completion callback handler will receive {@link #EVENT_GET_MESSAGE} - * - * @param handle handle of message to retrieve - * @param charset {@link CharsetType} object corresponding to - * <code>Charset</code> application parameter in MAP - * specification - * @param attachment corresponds to <code>Attachment</code> application - * parameter in MAP specification - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean getMessage(String handle, boolean attachment) { - if (mObexSession == null) { - return false; - } - - try { - /* just to validate */ - new BigInteger(handle, 16); - } catch (NumberFormatException e) { - return false; - } - - // Since we support only text messaging via Bluetooth, it is OK to restrict the requests to - // force conversion to UTF-8. - BluetoothMasRequest request = - new BluetoothMasRequestGetMessage(handle, CharsetType.UTF_8, attachment); - return mObexSession.makeRequest(request); - } - - /** - * Sets read status of message on MSE - * <p> - * Upon completion callback handler will receive - * {@link #EVENT_SET_MESSAGE_STATUS} - * - * @param handle handle of message - * @param read <code>true</code> for "read", <code>false</code> for "unread" - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean setMessageReadStatus(String handle, boolean read) { - if (mObexSession == null) { - return false; - } - - try { - /* just to validate */ - new BigInteger(handle, 16); - } catch (NumberFormatException e) { - return false; - } - - BluetoothMasRequest request = new BluetoothMasRequestSetMessageStatus(handle, - StatusIndicator.READ, read); - return mObexSession.makeRequest(request); - } - - /** - * Sets deleted status of message on MSE - * <p> - * Upon completion callback handler will receive - * {@link #EVENT_SET_MESSAGE_STATUS} - * - * @param handle handle of message - * @param deleted <code>true</code> for "deleted", <code>false</code> for - * "undeleted" - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean setMessageDeletedStatus(String handle, boolean deleted) { - if (mObexSession == null) { - return false; - } - - try { - /* just to validate */ - new BigInteger(handle, 16); - } catch (NumberFormatException e) { - return false; - } - - BluetoothMasRequest request = new BluetoothMasRequestSetMessageStatus(handle, - StatusIndicator.DELETED, deleted); - return mObexSession.makeRequest(request); - } - - /** - * Pushes new message to MSE - * <p> - * Upon completion callback handler will receive {@link #EVENT_PUSH_MESSAGE} - * - * @param folder name of sub-folder to push to or <code>null</code> for - * current folder - * @param charset {@link CharsetType} object corresponding to - * <code>Charset</code> application parameter in MAP - * specification - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean pushMessage(String folder, BluetoothMapBmessage bmsg, CharsetType charset) { - return pushMessage(folder, bmsg, charset, false, false); - } - - /** - * Pushes new message to MSE - * <p> - * Upon completion callback handler will receive {@link #EVENT_PUSH_MESSAGE} - * - * @param folder name of sub-folder to push to or <code>null</code> for - * current folder - * @param bmsg {@link BluetoothMapBmessage} object representing message to - * be pushed - * @param charset {@link CharsetType} object corresponding to - * <code>Charset</code> application parameter in MAP - * specification - * @param transparent corresponds to <code>Transparent</code> application - * parameter in MAP specification - * @param retry corresponds to <code>Transparent</code> application - * parameter in MAP specification - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean pushMessage(String folder, BluetoothMapBmessage bmsg, CharsetType charset, - boolean transparent, boolean retry) { - if (mObexSession == null) { - return false; - } - - String bmsgString = BluetoothMapBmessageBuilder.createBmessage(bmsg); - - BluetoothMasRequest request = - new BluetoothMasRequestPushMessage(folder, bmsgString, charset, transparent, retry); - return mObexSession.makeRequest(request); - } - - /** - * Requests MSE to initiate ubdate of inbox - * <p> - * Upon completion callback handler will receive {@link #EVENT_UPDATE_INBOX} - * - * @return <code>true</code> if request has been sent, <code>false</code> - * otherwise - */ - public boolean updateInbox() { - if (mObexSession == null) { - return false; - } - - BluetoothMasRequest request = new BluetoothMasRequestUpdateInbox(); - return mObexSession.makeRequest(request); - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMasObexClientSession.java b/src/android/bluetooth/client/map/BluetoothMasObexClientSession.java deleted file mode 100644 index 9bf75d4..0000000 --- a/src/android/bluetooth/client/map/BluetoothMasObexClientSession.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.os.Process; -import android.util.Log; - -import java.io.IOException; -import java.lang.ref.WeakReference; - -import javax.obex.ClientSession; -import javax.obex.HeaderSet; -import javax.obex.ObexTransport; -import javax.obex.ResponseCodes; - -class BluetoothMasObexClientSession { - private static final String TAG = "BluetoothMasObexClientSession"; - - private static final byte[] MAS_TARGET = new byte[] { - (byte) 0xbb, 0x58, 0x2b, 0x40, 0x42, 0x0c, 0x11, (byte) 0xdb, (byte) 0xb0, (byte) 0xde, - 0x08, 0x00, 0x20, 0x0c, (byte) 0x9a, 0x66 - }; - - private boolean DBG = true; - - static final int MSG_OBEX_CONNECTED = 100; - static final int MSG_OBEX_DISCONNECTED = 101; - static final int MSG_REQUEST_COMPLETED = 102; - - private static final int CONNECT = 0; - private static final int DISCONNECT = 1; - private static final int REQUEST = 2; - - private final ObexTransport mTransport; - - private final Handler mSessionHandler; - - private ClientSession mSession; - - private HandlerThread mThread; - private Handler mHandler; - - private boolean mConnected; - - private static class ObexClientHandler extends Handler { - WeakReference<BluetoothMasObexClientSession> mInst; - - ObexClientHandler(Looper looper, BluetoothMasObexClientSession inst) { - super(looper); - mInst = new WeakReference<BluetoothMasObexClientSession>(inst); - } - - @Override - public void handleMessage(Message msg) { - BluetoothMasObexClientSession inst = mInst.get(); - if (!inst.connected() && msg.what != CONNECT) { - Log.w(TAG, "Cannot execute " + msg + " when not CONNECTED."); - return; - } - - switch (msg.what) { - case CONNECT: - inst.connect(); - break; - - case DISCONNECT: - inst.disconnect(); - break; - - case REQUEST: - inst.executeRequest((BluetoothMasRequest) msg.obj); - break; - } - } - } - - public BluetoothMasObexClientSession(ObexTransport transport, Handler handler) { - mTransport = transport; - mSessionHandler = handler; - } - - public void start() { - if (DBG) Log.d(TAG, "start called."); - if (mConnected) { - if (DBG) Log.d(TAG, "Already connected, nothing to do."); - return; - } - - // Start a thread to handle messages here. - mThread = new HandlerThread("BluetoothMasObexClientSessionThread"); - mThread.start(); - mHandler = new ObexClientHandler(mThread.getLooper(), this); - - // Connect it to the target device via OBEX. - mHandler.obtainMessage(CONNECT).sendToTarget(); - } - - public boolean makeRequest(BluetoothMasRequest request) { - if (DBG) Log.d(TAG, "makeRequest called with: " + request); - - boolean status = mHandler.sendMessage(mHandler.obtainMessage(REQUEST, request)); - if (!status) { - Log.e(TAG, "Adding messages failed, state: " + mConnected); - return false; - } - return true; - } - - public void stop() { - if (DBG) Log.d(TAG, "stop called..."); - - mThread.quit(); - disconnect(); - } - - private void connect() { - try { - mSession = new ClientSession(mTransport); - - HeaderSet headerset = new HeaderSet(); - headerset.setHeader(HeaderSet.TARGET, MAS_TARGET); - - headerset = mSession.connect(headerset); - - if (headerset.getResponseCode() == ResponseCodes.OBEX_HTTP_OK) { - mConnected = true; - mSessionHandler.obtainMessage(MSG_OBEX_CONNECTED).sendToTarget(); - } else { - disconnect(); - } - } catch (IOException e) { - disconnect(); - } - } - - private void disconnect() { - if (mSession != null) { - try { - mSession.disconnect(null); - } catch (IOException e) { - } - - try { - mSession.close(); - } catch (IOException e) { - } - } - - mConnected = false; - mSessionHandler.obtainMessage(MSG_OBEX_DISCONNECTED).sendToTarget(); - } - - private void executeRequest(BluetoothMasRequest request) { - try { - request.execute(mSession); - mSessionHandler.obtainMessage(MSG_REQUEST_COMPLETED, request).sendToTarget(); - } catch (IOException e) { - if (DBG) Log.d(TAG, "Request failed: " + request); - - // Disconnect to cleanup. - disconnect(); - } - } - - - private boolean connected() { - return mConnected; - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMasRequest.java b/src/android/bluetooth/client/map/BluetoothMasRequest.java deleted file mode 100644 index 0c9c29c..0000000 --- a/src/android/bluetooth/client/map/BluetoothMasRequest.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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 java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import javax.obex.ClientOperation; -import javax.obex.ClientSession; -import javax.obex.HeaderSet; -import javax.obex.Operation; -import javax.obex.ResponseCodes; - -abstract class BluetoothMasRequest { - - protected static final byte OAP_TAGID_MAX_LIST_COUNT = 0x01; - protected static final byte OAP_TAGID_START_OFFSET = 0x02; - protected static final byte OAP_TAGID_FILTER_MESSAGE_TYPE = 0x03; - protected static final byte OAP_TAGID_FILTER_PERIOD_BEGIN = 0x04; - protected static final byte OAP_TAGID_FILTER_PERIOD_END = 0x05; - protected static final byte OAP_TAGID_FILTER_READ_STATUS = 0x06; - protected static final byte OAP_TAGID_FILTER_RECIPIENT = 0x07; - protected static final byte OAP_TAGID_FILTER_ORIGINATOR = 0x08; - protected static final byte OAP_TAGID_FILTER_PRIORITY = 0x09; - protected static final byte OAP_TAGID_ATTACHMENT = 0x0a; - protected static final byte OAP_TAGID_TRANSPARENT = 0xb; - protected static final byte OAP_TAGID_RETRY = 0xc; - protected static final byte OAP_TAGID_NEW_MESSAGE = 0x0d; - protected static final byte OAP_TAGID_NOTIFICATION_STATUS = 0x0e; - protected static final byte OAP_TAGID_MAS_INSTANCE_ID = 0x0f; - protected static final byte OAP_TAGID_PARAMETER_MASK = 0x10; - protected static final byte OAP_TAGID_FOLDER_LISTING_SIZE = 0x11; - protected static final byte OAP_TAGID_MESSAGES_LISTING_SIZE = 0x12; - protected static final byte OAP_TAGID_SUBJECT_LENGTH = 0x13; - protected static final byte OAP_TAGID_CHARSET = 0x14; - protected static final byte OAP_TAGID_STATUS_INDICATOR = 0x17; - protected static final byte OAP_TAGID_STATUS_VALUE = 0x18; - protected static final byte OAP_TAGID_MSE_TIME = 0x19; - - protected static byte NOTIFICATION_ON = 0x01; - protected static byte NOTIFICATION_OFF = 0x00; - - protected static byte ATTACHMENT_ON = 0x01; - protected static byte ATTACHMENT_OFF = 0x00; - - protected static byte CHARSET_NATIVE = 0x00; - protected static byte CHARSET_UTF8 = 0x01; - - protected static byte STATUS_INDICATOR_READ = 0x00; - protected static byte STATUS_INDICATOR_DELETED = 0x01; - - protected static byte STATUS_NO = 0x00; - protected static byte STATUS_YES = 0x01; - - protected static byte TRANSPARENT_OFF = 0x00; - protected static byte TRANSPARENT_ON = 0x01; - - protected static byte RETRY_OFF = 0x00; - protected static byte RETRY_ON = 0x01; - - /* used for PUT requests which require filler byte */ - protected static final byte[] FILLER_BYTE = { - 0x30 - }; - - protected HeaderSet mHeaderSet; - - protected int mResponseCode; - - public BluetoothMasRequest() { - mHeaderSet = new HeaderSet(); - } - - abstract public void execute(ClientSession session) throws IOException; - - protected void executeGet(ClientSession session) throws IOException { - ClientOperation op = null; - - try { - op = (ClientOperation) session.get(mHeaderSet); - - /* - * MAP spec does not explicitly require that GET request should be - * sent in single packet but for some reason PTS complains when - * final GET packet with no headers follows non-final GET with all - * headers. So this is workaround, at least temporary. TODO: check - * with PTS - */ - op.setGetFinalFlag(true); - - /* - * this will trigger ClientOperation to use non-buffered stream so - * we can abort operation - */ - op.continueOperation(true, false); - - readResponseHeaders(op.getReceivedHeader()); - - InputStream is = op.openInputStream(); - readResponse(is); - is.close(); - - op.close(); - - mResponseCode = op.getResponseCode(); - } catch (IOException e) { - mResponseCode = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; - - throw e; - } - } - - protected void executePut(ClientSession session, byte[] body) throws IOException { - Operation op = null; - - mHeaderSet.setHeader(HeaderSet.LENGTH, Long.valueOf(body.length)); - - try { - op = session.put(mHeaderSet); - - DataOutputStream out = op.openDataOutputStream(); - out.write(body); - out.close(); - - readResponseHeaders(op.getReceivedHeader()); - - op.close(); - mResponseCode = op.getResponseCode(); - } catch (IOException e) { - mResponseCode = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; - - throw e; - } - } - - final public boolean isSuccess() { - return (mResponseCode == ResponseCodes.OBEX_HTTP_OK); - } - - protected void readResponse(InputStream stream) throws IOException { - /* nothing here by default */ - } - - protected void readResponseHeaders(HeaderSet headerset) { - /* nothing here by default */ - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMasRequestGetFolderListing.java b/src/android/bluetooth/client/map/BluetoothMasRequestGetFolderListing.java deleted file mode 100644 index db22ada..0000000 --- a/src/android/bluetooth/client/map/BluetoothMasRequestGetFolderListing.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.bluetooth.client.map.utils.ObexAppParameters; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; - -import javax.obex.ClientSession; -import javax.obex.HeaderSet; - -final class BluetoothMasRequestGetFolderListing extends BluetoothMasRequest { - - private static final String TYPE = "x-obex/folder-listing"; - - private BluetoothMapFolderListing mResponse = null; - - public BluetoothMasRequestGetFolderListing(int maxListCount, int listStartOffset) { - - if (maxListCount < 0 || maxListCount > 65535) { - throw new IllegalArgumentException("maxListCount should be [0..65535]"); - } - - if (listStartOffset < 0 || listStartOffset > 65535) { - throw new IllegalArgumentException("listStartOffset should be [0..65535]"); - } - - mHeaderSet.setHeader(HeaderSet.TYPE, TYPE); - - ObexAppParameters oap = new ObexAppParameters(); - // Allow GetFolderListing for maxListCount value 0 also. - if (maxListCount >= 0) { - oap.add(OAP_TAGID_MAX_LIST_COUNT, (short) maxListCount); - } - - if (listStartOffset > 0) { - oap.add(OAP_TAGID_START_OFFSET, (short) listStartOffset); - } - - oap.addToHeaderSet(mHeaderSet); - } - - @Override - protected void readResponse(InputStream stream) { - mResponse = new BluetoothMapFolderListing(stream); - } - - public ArrayList<String> getList() { - if (mResponse == null) { - return null; - } - - return mResponse.getList(); - } - - @Override - public void execute(ClientSession session) throws IOException { - executeGet(session); - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMasRequestGetFolderListingSize.java b/src/android/bluetooth/client/map/BluetoothMasRequestGetFolderListingSize.java deleted file mode 100644 index 910c036..0000000 --- a/src/android/bluetooth/client/map/BluetoothMasRequestGetFolderListingSize.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.bluetooth.client.map.utils.ObexAppParameters; - -import java.io.IOException; - -import javax.obex.ClientSession; -import javax.obex.HeaderSet; - -final class BluetoothMasRequestGetFolderListingSize extends BluetoothMasRequest { - - private static final String TYPE = "x-obex/folder-listing"; - - private int mSize; - - public BluetoothMasRequestGetFolderListingSize() { - mHeaderSet.setHeader(HeaderSet.TYPE, TYPE); - - ObexAppParameters oap = new ObexAppParameters(); - oap.add(OAP_TAGID_MAX_LIST_COUNT, 0); - - oap.addToHeaderSet(mHeaderSet); - } - - @Override - protected void readResponseHeaders(HeaderSet headerset) { - ObexAppParameters oap = ObexAppParameters.fromHeaderSet(headerset); - - mSize = oap.getShort(OAP_TAGID_FOLDER_LISTING_SIZE); - } - - public int getSize() { - return mSize; - } - - @Override - public void execute(ClientSession session) throws IOException { - executeGet(session); - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMasRequestGetMessage.java b/src/android/bluetooth/client/map/BluetoothMasRequestGetMessage.java deleted file mode 100644 index 923bff0..0000000 --- a/src/android/bluetooth/client/map/BluetoothMasRequestGetMessage.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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 android.bluetooth.client.map.BluetoothMasClient.CharsetType; -import android.bluetooth.client.map.utils.ObexAppParameters; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.nio.charset.StandardCharsets; - -import javax.obex.ClientSession; -import javax.obex.HeaderSet; -import javax.obex.ResponseCodes; - -final class BluetoothMasRequestGetMessage extends BluetoothMasRequest { - - private static final String TAG = "BluetoothMasRequestGetMessage"; - - private static final String TYPE = "x-bt/message"; - - private BluetoothMapBmessage mBmessage; - - public BluetoothMasRequestGetMessage(String handle, CharsetType charset, boolean attachment) { - - mHeaderSet.setHeader(HeaderSet.NAME, handle); - - mHeaderSet.setHeader(HeaderSet.TYPE, TYPE); - - ObexAppParameters oap = new ObexAppParameters(); - - oap.add(OAP_TAGID_CHARSET, CharsetType.UTF_8.equals(charset) ? CHARSET_UTF8 - : CHARSET_NATIVE); - - oap.add(OAP_TAGID_ATTACHMENT, attachment ? ATTACHMENT_ON : ATTACHMENT_OFF); - - oap.addToHeaderSet(mHeaderSet); - } - - @Override - protected void readResponse(InputStream stream) { - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buf = new byte[1024]; - - try { - int len; - while ((len = stream.read(buf)) != -1) { - baos.write(buf, 0, len); - } - } catch (IOException e) { - Log.e(TAG, "I/O exception while reading response", e); - } - - // Convert the input stream using UTF-8 since the attributes in the payload are all encoded - // according to it. The actual message body may need to be transcoded depending on - // charset/encoding defined for body-content. - String bmsg; - try { - bmsg = baos.toString(StandardCharsets.UTF_8.name()); - } catch (UnsupportedEncodingException ex) { - Log.e(TAG, - "Coudn't decode the bmessage with UTF-8. Something must be really messed up."); - return; - } - - mBmessage = BluetoothMapBmessageParser.createBmessage(bmsg); - - if (mBmessage == null) { - mResponseCode = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; - } - } - - public BluetoothMapBmessage getMessage() { - return mBmessage; - } - - @Override - public void execute(ClientSession session) throws IOException { - executeGet(session); - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMasRequestGetMessagesListing.java b/src/android/bluetooth/client/map/BluetoothMasRequestGetMessagesListing.java deleted file mode 100644 index 2ad167d..0000000 --- a/src/android/bluetooth/client/map/BluetoothMasRequestGetMessagesListing.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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.bluetooth.client.map.BluetoothMasClient.MessagesFilter; -import android.bluetooth.client.map.utils.ObexAppParameters; -import android.bluetooth.client.map.utils.ObexTime; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Date; - -import javax.obex.ClientSession; -import javax.obex.HeaderSet; - -final class BluetoothMasRequestGetMessagesListing extends BluetoothMasRequest { - - private static final String TYPE = "x-bt/MAP-msg-listing"; - - private BluetoothMapMessagesListing mResponse = null; - - private boolean mNewMessage = false; - - private Date mServerTime = null; - - public BluetoothMasRequestGetMessagesListing(String folderName, int parameters, - BluetoothMasClient.MessagesFilter filter, int subjectLength, int maxListCount, - int listStartOffset) { - if (subjectLength < 0 || subjectLength > 255) { - throw new IllegalArgumentException("subjectLength should be [0..255]"); - } - - if (maxListCount < 0 || maxListCount > 65535) { - throw new IllegalArgumentException("maxListCount should be [0..65535]"); - } - - if (listStartOffset < 0 || listStartOffset > 65535) { - throw new IllegalArgumentException("listStartOffset should be [0..65535]"); - } - - mHeaderSet.setHeader(HeaderSet.TYPE, TYPE); - - if (folderName == null) { - mHeaderSet.setHeader(HeaderSet.NAME, ""); - } else { - mHeaderSet.setHeader(HeaderSet.NAME, folderName); - } - - ObexAppParameters oap = new ObexAppParameters(); - - if (filter != null) { - if (filter.messageType != MessagesFilter.MESSAGE_TYPE_ALL) { - oap.add(OAP_TAGID_FILTER_MESSAGE_TYPE, filter.messageType); - } - - if (filter.periodBegin != null) { - oap.add(OAP_TAGID_FILTER_PERIOD_BEGIN, filter.periodBegin); - } - - if (filter.periodEnd != null) { - oap.add(OAP_TAGID_FILTER_PERIOD_END, filter.periodEnd); - } - - if (filter.readStatus != MessagesFilter.READ_STATUS_ANY) { - oap.add(OAP_TAGID_FILTER_READ_STATUS, filter.readStatus); - } - - if (filter.recipient != null) { - oap.add(OAP_TAGID_FILTER_RECIPIENT, filter.recipient); - } - - if (filter.originator != null) { - oap.add(OAP_TAGID_FILTER_ORIGINATOR, filter.originator); - } - - if (filter.priority != MessagesFilter.PRIORITY_ANY) { - oap.add(OAP_TAGID_FILTER_PRIORITY, filter.priority); - } - } - - if (subjectLength != 0) { - oap.add(OAP_TAGID_SUBJECT_LENGTH, (byte) subjectLength); - } - /* Include parameterMask only when specific values are selected, - * to avoid IOT specific issue with no paramterMask header support. - */ - if (parameters > 0 ) { - oap.add(OAP_TAGID_PARAMETER_MASK, parameters); - } - // Allow GetMessageListing for maxlistcount value 0 also. - if (maxListCount >= 0) { - oap.add(OAP_TAGID_MAX_LIST_COUNT, (short) maxListCount); - } - - if (listStartOffset != 0) { - oap.add(OAP_TAGID_START_OFFSET, (short) listStartOffset); - } - - oap.addToHeaderSet(mHeaderSet); - } - - @Override - protected void readResponse(InputStream stream) { - mResponse = new BluetoothMapMessagesListing(stream); - } - - @Override - protected void readResponseHeaders(HeaderSet headerset) { - ObexAppParameters oap = ObexAppParameters.fromHeaderSet(headerset); - - mNewMessage = ((oap.getByte(OAP_TAGID_NEW_MESSAGE) & 0x01) == 1); - - if (oap.exists(OAP_TAGID_MSE_TIME)) { - String mseTime = oap.getString(OAP_TAGID_MSE_TIME); - if(mseTime != null ) - mServerTime = (new ObexTime(mseTime)).getTime(); - } - } - - public ArrayList<BluetoothMapMessage> getList() { - if (mResponse == null) { - return null; - } - - return mResponse.getList(); - } - - public boolean getNewMessageStatus() { - return mNewMessage; - } - - public Date getMseTime() { - return mServerTime; - } - - @Override - public void execute(ClientSession session) throws IOException { - executeGet(session); - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMasRequestGetMessagesListingSize.java b/src/android/bluetooth/client/map/BluetoothMasRequestGetMessagesListingSize.java deleted file mode 100644 index cdadb2e..0000000 --- a/src/android/bluetooth/client/map/BluetoothMasRequestGetMessagesListingSize.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.bluetooth.client.map.utils.ObexAppParameters; - -import java.io.IOException; - -import javax.obex.ClientSession; -import javax.obex.HeaderSet; - -final class BluetoothMasRequestGetMessagesListingSize extends BluetoothMasRequest { - - private static final String TYPE = "x-bt/MAP-msg-listing"; - - private int mSize; - - public BluetoothMasRequestGetMessagesListingSize() { - mHeaderSet.setHeader(HeaderSet.NAME, ""); - mHeaderSet.setHeader(HeaderSet.TYPE, TYPE); - - ObexAppParameters oap = new ObexAppParameters(); - oap.add(OAP_TAGID_MAX_LIST_COUNT, (short) 0); - - oap.addToHeaderSet(mHeaderSet); - } - - @Override - protected void readResponseHeaders(HeaderSet headerset) { - ObexAppParameters oap = ObexAppParameters.fromHeaderSet(headerset); - - mSize = oap.getShort(OAP_TAGID_MESSAGES_LISTING_SIZE); - } - - public int getSize() { - return mSize; - } - - @Override - public void execute(ClientSession session) throws IOException { - executeGet(session); - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMasRequestPushMessage.java b/src/android/bluetooth/client/map/BluetoothMasRequestPushMessage.java deleted file mode 100644 index 8fc9bd4..0000000 --- a/src/android/bluetooth/client/map/BluetoothMasRequestPushMessage.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 java.io.IOException; -import java.math.BigInteger; - -import javax.obex.ClientSession; -import javax.obex.HeaderSet; -import javax.obex.ResponseCodes; - -import android.bluetooth.client.map.BluetoothMasClient.CharsetType; -import android.bluetooth.client.map.utils.ObexAppParameters; - -final class BluetoothMasRequestPushMessage extends BluetoothMasRequest { - - private static final String TYPE = "x-bt/message"; - private String mMsg; - private String mMsgHandle; - - private BluetoothMasRequestPushMessage(String folder) { - mHeaderSet.setHeader(HeaderSet.TYPE, TYPE); - if (folder == null) { - folder = ""; - } - mHeaderSet.setHeader(HeaderSet.NAME, folder); - } - - public BluetoothMasRequestPushMessage(String folder, String msg, CharsetType charset, - boolean transparent, boolean retry) { - this(folder); - mMsg = msg; - ObexAppParameters oap = new ObexAppParameters(); - oap.add(OAP_TAGID_TRANSPARENT, transparent ? TRANSPARENT_ON : TRANSPARENT_OFF); - oap.add(OAP_TAGID_RETRY, retry ? RETRY_ON : RETRY_OFF); - oap.add(OAP_TAGID_CHARSET, charset == CharsetType.NATIVE ? CHARSET_NATIVE : CHARSET_UTF8); - oap.addToHeaderSet(mHeaderSet); - } - - @Override - protected void readResponseHeaders(HeaderSet headerset) { - try { - String handle = (String) headerset.getHeader(HeaderSet.NAME); - if (handle != null) { - /* just to validate */ - new BigInteger(handle, 16); - - mMsgHandle = handle; - } - } catch (NumberFormatException e) { - mResponseCode = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; - } catch (IOException e) { - mResponseCode = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; - } - } - - public String getMsgHandle() { - return mMsgHandle; - } - - @Override - public void execute(ClientSession session) throws IOException { - executePut(session, mMsg.getBytes()); - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMasRequestSetMessageStatus.java b/src/android/bluetooth/client/map/BluetoothMasRequestSetMessageStatus.java deleted file mode 100644 index 140312e..0000000 --- a/src/android/bluetooth/client/map/BluetoothMasRequestSetMessageStatus.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.bluetooth.client.map.utils.ObexAppParameters; - -import java.io.IOException; - -import javax.obex.ClientSession; -import javax.obex.HeaderSet; - -final class BluetoothMasRequestSetMessageStatus extends BluetoothMasRequest { - - public enum StatusIndicator { - READ, DELETED; - } - - private static final String TYPE = "x-bt/messageStatus"; - - public BluetoothMasRequestSetMessageStatus(String handle, StatusIndicator statusInd, - boolean statusValue) { - - mHeaderSet.setHeader(HeaderSet.TYPE, TYPE); - mHeaderSet.setHeader(HeaderSet.NAME, handle); - - ObexAppParameters oap = new ObexAppParameters(); - oap.add(OAP_TAGID_STATUS_INDICATOR, - statusInd == StatusIndicator.READ ? STATUS_INDICATOR_READ - : STATUS_INDICATOR_DELETED); - oap.add(OAP_TAGID_STATUS_VALUE, statusValue ? STATUS_YES : STATUS_NO); - oap.addToHeaderSet(mHeaderSet); - } - - @Override - public void execute(ClientSession session) throws IOException { - executePut(session, FILLER_BYTE); - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMasRequestSetNotificationRegistration.java b/src/android/bluetooth/client/map/BluetoothMasRequestSetNotificationRegistration.java deleted file mode 100644 index debb508..0000000 --- a/src/android/bluetooth/client/map/BluetoothMasRequestSetNotificationRegistration.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.bluetooth.client.map.utils.ObexAppParameters; - -import java.io.IOException; - -import javax.obex.ClientSession; -import javax.obex.HeaderSet; - -final class BluetoothMasRequestSetNotificationRegistration extends BluetoothMasRequest { - - private static final String TYPE = "x-bt/MAP-NotificationRegistration"; - - private final boolean mStatus; - - public BluetoothMasRequestSetNotificationRegistration(boolean status) { - mStatus = status; - - mHeaderSet.setHeader(HeaderSet.TYPE, TYPE); - - ObexAppParameters oap = new ObexAppParameters(); - - oap.add(OAP_TAGID_NOTIFICATION_STATUS, status ? NOTIFICATION_ON : NOTIFICATION_OFF); - - oap.addToHeaderSet(mHeaderSet); - } - - @Override - public void execute(ClientSession session) throws IOException { - executePut(session, FILLER_BYTE); - } - - public boolean getStatus() { - return mStatus; - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMasRequestSetPath.java b/src/android/bluetooth/client/map/BluetoothMasRequestSetPath.java deleted file mode 100644 index 71e2dbe..0000000 --- a/src/android/bluetooth/client/map/BluetoothMasRequestSetPath.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 java.io.IOException; - -import javax.obex.ClientSession; -import javax.obex.HeaderSet; -import javax.obex.ResponseCodes; - -class BluetoothMasRequestSetPath extends BluetoothMasRequest { - - enum SetPathDir { - ROOT, UP, DOWN - }; - - SetPathDir mDir; - - String mName; - - public BluetoothMasRequestSetPath(String name) { - mDir = SetPathDir.DOWN; - mName = name; - - mHeaderSet.setHeader(HeaderSet.NAME, name); - } - - public BluetoothMasRequestSetPath(boolean goRoot) { - mHeaderSet.setEmptyNameHeader(); - if (goRoot) { - mDir = SetPathDir.ROOT; - } else { - mDir = SetPathDir.UP; - } - } - - @Override - public void execute(ClientSession session) { - HeaderSet hs = null; - - try { - switch (mDir) { - case ROOT: - case DOWN: - hs = session.setPath(mHeaderSet, false, false); - break; - case UP: - hs = session.setPath(mHeaderSet, true, false); - break; - } - - mResponseCode = hs.getResponseCode(); - } catch (IOException e) { - mResponseCode = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; - } - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMasRequestUpdateInbox.java b/src/android/bluetooth/client/map/BluetoothMasRequestUpdateInbox.java deleted file mode 100644 index aeec632..0000000 --- a/src/android/bluetooth/client/map/BluetoothMasRequestUpdateInbox.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 java.io.IOException; - -import javax.obex.ClientSession; -import javax.obex.HeaderSet; - -final class BluetoothMasRequestUpdateInbox extends BluetoothMasRequest { - - private static final String TYPE = "x-bt/MAP-messageUpdate"; - - public BluetoothMasRequestUpdateInbox() { - mHeaderSet.setHeader(HeaderSet.TYPE, TYPE); - } - - @Override - public void execute(ClientSession session) throws IOException { - executePut(session, FILLER_BYTE); - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMnsObexServer.java b/src/android/bluetooth/client/map/BluetoothMnsObexServer.java deleted file mode 100644 index 672e9cf..0000000 --- a/src/android/bluetooth/client/map/BluetoothMnsObexServer.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * 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.os.Handler; -import android.util.Log; - -import android.bluetooth.client.map.utils.ObexAppParameters; - -import java.io.IOException; -import java.util.Arrays; - -import javax.obex.HeaderSet; -import javax.obex.Operation; -import javax.obex.ResponseCodes; -import javax.obex.ServerRequestHandler; - -class BluetoothMnsObexServer extends ServerRequestHandler { - - private final static String TAG = "BluetoothMnsObexServer"; - - private static final byte[] MNS_TARGET = new byte[] { - (byte) 0xbb, 0x58, 0x2b, 0x41, 0x42, 0x0c, 0x11, (byte) 0xdb, (byte) 0xb0, (byte) 0xde, - 0x08, 0x00, 0x20, 0x0c, (byte) 0x9a, 0x66 - }; - - private final static String TYPE = "x-bt/MAP-event-report"; - - private final Handler mCallback; - - public BluetoothMnsObexServer(Handler callback) { - super(); - - mCallback = callback; - } - - @Override - public int onConnect(final HeaderSet request, HeaderSet reply) { - Log.v(TAG, "onConnect"); - - try { - byte[] uuid = (byte[]) request.getHeader(HeaderSet.TARGET); - - if (!Arrays.equals(uuid, MNS_TARGET)) { - return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE; - } - - } catch (IOException e) { - // this should never happen since getHeader won't throw exception it - // declares to throw - return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; - } - - reply.setHeader(HeaderSet.WHO, MNS_TARGET); - return ResponseCodes.OBEX_HTTP_OK; - } - - @Override - public void onDisconnect(final HeaderSet request, HeaderSet reply) { - Log.v(TAG, "onDisconnect"); - } - - @Override - public int onGet(final Operation op) { - Log.v(TAG, "onGet"); - - return ResponseCodes.OBEX_HTTP_BAD_REQUEST; - } - - @Override - public int onPut(final Operation op) { - Log.v(TAG, "onPut"); - - try { - HeaderSet headerset; - headerset = op.getReceivedHeader(); - - String type = (String) headerset.getHeader(HeaderSet.TYPE); - ObexAppParameters oap = ObexAppParameters.fromHeaderSet(headerset); - - if (!TYPE.equals(type) || !oap.exists(BluetoothMasRequest.OAP_TAGID_MAS_INSTANCE_ID)) { - return ResponseCodes.OBEX_HTTP_BAD_REQUEST; - } - - Byte inst = oap.getByte(BluetoothMasRequest.OAP_TAGID_MAS_INSTANCE_ID); - - BluetoothMapEventReport ev = BluetoothMapEventReport.fromStream(op - .openDataInputStream()); - - op.close(); - - mCallback.obtainMessage(BluetoothMnsService.MSG_EVENT, inst, 0, ev).sendToTarget(); - } catch (IOException e) { - Log.e(TAG, "I/O exception when handling PUT request", e); - return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; - } - - return ResponseCodes.OBEX_HTTP_OK; - } - - @Override - public int onAbort(final HeaderSet request, HeaderSet reply) { - Log.v(TAG, "onAbort"); - - return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED; - } - - @Override - public int onSetPath(final HeaderSet request, HeaderSet reply, - final boolean backup, final boolean create) { - Log.v(TAG, "onSetPath"); - - return ResponseCodes.OBEX_HTTP_BAD_REQUEST; - } - - @Override - public void onClose() { - Log.v(TAG, "onClose"); - - // TODO: call session handler so it can disconnect - } -} diff --git a/src/android/bluetooth/client/map/BluetoothMnsService.java b/src/android/bluetooth/client/map/BluetoothMnsService.java deleted file mode 100644 index 42175e0..0000000 --- a/src/android/bluetooth/client/map/BluetoothMnsService.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * 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.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothServerSocket; -import android.bluetooth.BluetoothSocket; -import android.os.Handler; -import android.os.Message; -import android.os.ParcelUuid; -import android.util.Log; -import android.util.SparseArray; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.lang.ref.WeakReference; - -import javax.obex.ServerSession; - -class BluetoothMnsService { - - private static final String TAG = "BluetoothMnsService"; - - private static final ParcelUuid MAP_MNS = - ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB"); - - static final int MSG_EVENT = 1; - - /* for BluetoothMasClient */ - static final int EVENT_REPORT = 1001; - - /* these are shared across instances */ - static private SparseArray<Handler> mCallbacks = null; - static private SocketAcceptThread mAcceptThread = null; - static private Handler mSessionHandler = null; - static private BluetoothServerSocket mServerSocket = null; - - private static class SessionHandler extends Handler { - - private final WeakReference<BluetoothMnsService> mService; - - SessionHandler(BluetoothMnsService service) { - mService = new WeakReference<BluetoothMnsService>(service); - } - - @Override - public void handleMessage(Message msg) { - Log.d(TAG, "Handler: msg: " + msg.what); - - switch (msg.what) { - case MSG_EVENT: - int instanceId = msg.arg1; - - synchronized (mCallbacks) { - Handler cb = mCallbacks.get(instanceId); - - if (cb != null) { - BluetoothMapEventReport ev = (BluetoothMapEventReport) msg.obj; - cb.obtainMessage(EVENT_REPORT, ev).sendToTarget(); - } else { - Log.w(TAG, "Got event for instance which is not registered: " - + instanceId); - } - } - break; - } - } - } - - private static class SocketAcceptThread extends Thread { - - private boolean mInterrupted = false; - - @Override - public void run() { - - if (mServerSocket != null) { - Log.w(TAG, "Socket already created, exiting"); - return; - } - - try { - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - mServerSocket = adapter.listenUsingEncryptedRfcommWithServiceRecord( - "MAP Message Notification Service", MAP_MNS.getUuid()); - } catch (IOException e) { - mInterrupted = true; - Log.e(TAG, "I/O exception when trying to create server socket", e); - } - - while (!mInterrupted) { - try { - Log.v(TAG, "waiting to accept connection..."); - - BluetoothSocket sock = mServerSocket.accept(); - - Log.v(TAG, "new incoming connection from " - + sock.getRemoteDevice().getName()); - - // session will live until closed by remote - BluetoothMnsObexServer srv = new BluetoothMnsObexServer(mSessionHandler); - BluetoothMapRfcommTransport transport = new BluetoothMapRfcommTransport( - sock); - new ServerSession(transport, srv, null); - } catch (IOException ex) { - Log.v(TAG, "I/O exception when waiting to accept (aborted?)"); - mInterrupted = true; - } - } - - if (mServerSocket != null) { - try { - mServerSocket.close(); - } catch (IOException e) { - // do nothing - } - - mServerSocket = null; - } - } - } - - BluetoothMnsService() { - Log.v(TAG, "BluetoothMnsService()"); - - if (mCallbacks == null) { - Log.v(TAG, "BluetoothMnsService(): allocating callbacks"); - mCallbacks = new SparseArray<Handler>(); - } - - if (mSessionHandler == null) { - Log.v(TAG, "BluetoothMnsService(): allocating session handler"); - mSessionHandler = new SessionHandler(this); - } - } - - public void registerCallback(int instanceId, Handler callback) { - Log.v(TAG, "registerCallback()"); - - synchronized (mCallbacks) { - mCallbacks.put(instanceId, callback); - - if (mAcceptThread == null) { - Log.v(TAG, "registerCallback(): starting MNS server"); - mAcceptThread = new SocketAcceptThread(); - mAcceptThread.setName("BluetoothMnsAcceptThread"); - mAcceptThread.start(); - } - } - } - - public void unregisterCallback(int instanceId) { - Log.v(TAG, "unregisterCallback()"); - - synchronized (mCallbacks) { - mCallbacks.remove(instanceId); - - if (mCallbacks.size() == 0) { - Log.v(TAG, "unregisterCallback(): shutting down MNS server"); - - if (mServerSocket != null) { - try { - mServerSocket.close(); - } catch (IOException e) { - } - - mServerSocket = null; - } - - mAcceptThread.interrupt(); - - try { - mAcceptThread.join(5000); - } catch (InterruptedException e) { - } - - mAcceptThread = null; - } - } - } -} diff --git a/src/android/bluetooth/client/map/utils/BmsgTokenizer.java b/src/android/bluetooth/client/map/utils/BmsgTokenizer.java deleted file mode 100644 index 9f23961..0000000 --- a/src/android/bluetooth/client/map/utils/BmsgTokenizer.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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.utils; - -import android.util.Log; - -import java.text.ParseException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public final class BmsgTokenizer { - - private final String mStr; - - private final Matcher mMatcher; - - private int mPos = 0; - - private final int mOffset; - - static public class Property { - public final String name; - public final String value; - - public Property(String name, String value) { - if (name == null || value == null) { - throw new IllegalArgumentException(); - } - - this.name = name; - this.value = value; - - Log.v("BMSG >> ", toString()); - } - - @Override - public String toString() { - return name + ":" + value; - } - - @Override - public boolean equals(Object o) { - return ((o instanceof Property) && ((Property) o).name.equals(name) && ((Property) o).value - .equals(value)); - } - }; - - public BmsgTokenizer(String str) { - this(str, 0); - } - - public BmsgTokenizer(String str, int offset) { - mStr = str; - mOffset = offset; - mMatcher = Pattern.compile("(([^:]*):(.*))?\r\n").matcher(str); - mPos = mMatcher.regionStart(); - } - - public Property next(boolean alwaysReturn) throws ParseException { - boolean found = false; - - do { - mMatcher.region(mPos, mMatcher.regionEnd()); - - if (!mMatcher.lookingAt()) { - if (alwaysReturn) { - return null; - } - - throw new ParseException("Property or empty line expected", pos()); - } - - mPos = mMatcher.end(); - - if (mMatcher.group(1) != null) { - found = true; - } - } while (!found); - - return new Property(mMatcher.group(2), mMatcher.group(3)); - } - - public Property next() throws ParseException { - return next(false); - } - - public String remaining() { - return mStr.substring(mPos); - } - - public int pos() { - return mPos + mOffset; - } -} diff --git a/src/android/bluetooth/client/map/utils/ObexAppParameters.java b/src/android/bluetooth/client/map/utils/ObexAppParameters.java deleted file mode 100644 index cae379b..0000000 --- a/src/android/bluetooth/client/map/utils/ObexAppParameters.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * 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.utils; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.HashMap; -import java.util.Map; - -import javax.obex.HeaderSet; - -public final class ObexAppParameters { - - private final HashMap<Byte, byte[]> mParams; - - public ObexAppParameters() { - mParams = new HashMap<Byte, byte[]>(); - } - - public ObexAppParameters(byte[] raw) { - mParams = new HashMap<Byte, byte[]>(); - - if (raw != null) { - for (int i = 0; i < raw.length;) { - if (raw.length - i < 2) { - break; - } - - byte tag = raw[i++]; - byte len = raw[i++]; - - if (raw.length - i - len < 0) { - break; - } - - byte[] val = new byte[len]; - - System.arraycopy(raw, i, val, 0, len); - this.add(tag, val); - - i += len; - } - } - } - - public static ObexAppParameters fromHeaderSet(HeaderSet headerset) { - try { - byte[] raw = (byte[]) headerset.getHeader(HeaderSet.APPLICATION_PARAMETER); - return new ObexAppParameters(raw); - } catch (IOException e) { - // won't happen - } - - return null; - } - - public byte[] getHeader() { - int length = 0; - - for (Map.Entry<Byte, byte[]> entry : mParams.entrySet()) { - length += (entry.getValue().length + 2); - } - - byte[] ret = new byte[length]; - - int idx = 0; - for (Map.Entry<Byte, byte[]> entry : mParams.entrySet()) { - length = entry.getValue().length; - - ret[idx++] = entry.getKey(); - ret[idx++] = (byte) length; - System.arraycopy(entry.getValue(), 0, ret, idx, length); - idx += length; - } - - return ret; - } - - public void addToHeaderSet(HeaderSet headerset) { - if (mParams.size() > 0) { - headerset.setHeader(HeaderSet.APPLICATION_PARAMETER, getHeader()); - } - } - - public boolean exists(byte tag) { - return mParams.containsKey(tag); - } - - public void add(byte tag, byte val) { - byte[] bval = ByteBuffer.allocate(1).put(val).array(); - mParams.put(tag, bval); - } - - public void add(byte tag, short val) { - byte[] bval = ByteBuffer.allocate(2).putShort(val).array(); - mParams.put(tag, bval); - } - - public void add(byte tag, int val) { - byte[] bval = ByteBuffer.allocate(4).putInt(val).array(); - mParams.put(tag, bval); - } - - public void add(byte tag, long val) { - byte[] bval = ByteBuffer.allocate(8).putLong(val).array(); - mParams.put(tag, bval); - } - - public void add(byte tag, String val) { - byte[] bval = val.getBytes(); - mParams.put(tag, bval); - } - - public void add(byte tag, byte[] bval) { - mParams.put(tag, bval); - } - - public byte getByte(byte tag) { - byte[] bval = mParams.get(tag); - - if (bval == null || bval.length < 1) { - return 0; - } - - return ByteBuffer.wrap(bval).get(); - } - - public short getShort(byte tag) { - byte[] bval = mParams.get(tag); - - if (bval == null || bval.length < 2) { - return 0; - } - - return ByteBuffer.wrap(bval).getShort(); - } - - public int getInt(byte tag) { - byte[] bval = mParams.get(tag); - - if (bval == null || bval.length < 4) { - return 0; - } - - return ByteBuffer.wrap(bval).getInt(); - } - - public String getString(byte tag) { - byte[] bval = mParams.get(tag); - - if (bval == null) { - return null; - } - - return new String(bval); - } - - public byte[] getByteArray(byte tag) { - byte[] bval = mParams.get(tag); - - return bval; - } - - @Override - public String toString() { - return mParams.toString(); - } -} diff --git a/src/android/bluetooth/client/map/utils/ObexTime.java b/src/android/bluetooth/client/map/utils/ObexTime.java deleted file mode 100644 index b35ce81..0000000 --- a/src/android/bluetooth/client/map/utils/ObexTime.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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.utils; - -import java.util.Calendar; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public final class ObexTime { - - private Date mDate; - - public ObexTime(String time) { - /* - * match OBEX time string: YYYYMMDDTHHMMSS with optional UTF offset - * +/-hhmm - */ - Pattern p = Pattern - .compile("(\\d{4})(\\d{2})(\\d{2})T(\\d{2})(\\d{2})(\\d{2})(([+-])(\\d{2})(\\d{2}))?"); - Matcher m = p.matcher(time); - - if (m.matches()) { - - /* - * matched groups are numberes as follows: YYYY MM DD T HH MM SS + - * hh mm ^^^^ ^^ ^^ ^^ ^^ ^^ ^ ^^ ^^ 1 2 3 4 5 6 8 9 10 all groups - * are guaranteed to be numeric so conversion will always succeed - * (except group 8 which is either + or -) - */ - - Calendar cal = Calendar.getInstance(); - cal.set(Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)) - 1, - Integer.parseInt(m.group(3)), Integer.parseInt(m.group(4)), - Integer.parseInt(m.group(5)), Integer.parseInt(m.group(6))); - - /* - * if 7th group is matched then we have UTC offset information - * included - */ - if (m.group(7) != null) { - int ohh = Integer.parseInt(m.group(9)); - int omm = Integer.parseInt(m.group(10)); - - /* time zone offset is specified in miliseconds */ - int offset = (ohh * 60 + omm) * 60 * 1000; - - if (m.group(8).equals("-")) { - offset = -offset; - } - - TimeZone tz = TimeZone.getTimeZone("UTC"); - tz.setRawOffset(offset); - - cal.setTimeZone(tz); - } - - mDate = cal.getTime(); - } - } - - public ObexTime(Date date) { - mDate = date; - } - - public Date getTime() { - return mDate; - } - - @Override - public String toString() { - if (mDate == null) { - return null; - } - - Calendar cal = Calendar.getInstance(); - cal.setTime(mDate); - - /* note that months are numbered stating from 0 */ - return String.format(Locale.US, "%04d%02d%02dT%02d%02d%02d", - cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, - cal.get(Calendar.DATE), cal.get(Calendar.HOUR_OF_DAY), - cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND)); - } -} |