1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.bluetooth.client.map; 18 19 import java.io.DataOutputStream; 20 import java.io.IOException; 21 import java.io.InputStream; 22 23 import javax.obex.ClientOperation; 24 import javax.obex.ClientSession; 25 import javax.obex.HeaderSet; 26 import javax.obex.Operation; 27 import javax.obex.ResponseCodes; 28 29 abstract class BluetoothMasRequest { 30 31 protected static final byte OAP_TAGID_MAX_LIST_COUNT = 0x01; 32 protected static final byte OAP_TAGID_START_OFFSET = 0x02; 33 protected static final byte OAP_TAGID_FILTER_MESSAGE_TYPE = 0x03; 34 protected static final byte OAP_TAGID_FILTER_PERIOD_BEGIN = 0x04; 35 protected static final byte OAP_TAGID_FILTER_PERIOD_END = 0x05; 36 protected static final byte OAP_TAGID_FILTER_READ_STATUS = 0x06; 37 protected static final byte OAP_TAGID_FILTER_RECIPIENT = 0x07; 38 protected static final byte OAP_TAGID_FILTER_ORIGINATOR = 0x08; 39 protected static final byte OAP_TAGID_FILTER_PRIORITY = 0x09; 40 protected static final byte OAP_TAGID_ATTACHMENT = 0x0a; 41 protected static final byte OAP_TAGID_TRANSPARENT = 0xb; 42 protected static final byte OAP_TAGID_RETRY = 0xc; 43 protected static final byte OAP_TAGID_NEW_MESSAGE = 0x0d; 44 protected static final byte OAP_TAGID_NOTIFICATION_STATUS = 0x0e; 45 protected static final byte OAP_TAGID_MAS_INSTANCE_ID = 0x0f; 46 protected static final byte OAP_TAGID_FOLDER_LISTING_SIZE = 0x11; 47 protected static final byte OAP_TAGID_MESSAGES_LISTING_SIZE = 0x12; 48 protected static final byte OAP_TAGID_SUBJECT_LENGTH = 0x13; 49 protected static final byte OAP_TAGID_CHARSET = 0x14; 50 protected static final byte OAP_TAGID_STATUS_INDICATOR = 0x17; 51 protected static final byte OAP_TAGID_STATUS_VALUE = 0x18; 52 protected static final byte OAP_TAGID_MSE_TIME = 0x19; 53 54 protected static byte NOTIFICATION_ON = 0x01; 55 protected static byte NOTIFICATION_OFF = 0x00; 56 57 protected static byte ATTACHMENT_ON = 0x01; 58 protected static byte ATTACHMENT_OFF = 0x00; 59 60 protected static byte CHARSET_NATIVE = 0x00; 61 protected static byte CHARSET_UTF8 = 0x01; 62 63 protected static byte STATUS_INDICATOR_READ = 0x00; 64 protected static byte STATUS_INDICATOR_DELETED = 0x01; 65 66 protected static byte STATUS_NO = 0x00; 67 protected static byte STATUS_YES = 0x01; 68 69 protected static byte TRANSPARENT_OFF = 0x00; 70 protected static byte TRANSPARENT_ON = 0x01; 71 72 protected static byte RETRY_OFF = 0x00; 73 protected static byte RETRY_ON = 0x01; 74 75 /* used for PUT requests which require filler byte */ 76 protected static final byte[] FILLER_BYTE = { 77 0x30 78 }; 79 80 protected HeaderSet mHeaderSet; 81 82 protected int mResponseCode; 83 84 public BluetoothMasRequest() { 85 mHeaderSet = new HeaderSet(); 86 } 87 88 abstract public void execute(ClientSession session) throws IOException; 89 90 protected void executeGet(ClientSession session) throws IOException { 91 ClientOperation op = null; 92 93 try { 94 op = (ClientOperation) session.get(mHeaderSet); 95 96 /* 97 * MAP spec does not explicitly require that GET request should be 98 * sent in single packet but for some reason PTS complains when 99 * final GET packet with no headers follows non-final GET with all 100 * headers. So this is workaround, at least temporary. TODO: check 101 * with PTS 102 */ 103 op.setGetFinalFlag(true); 104 105 /* 106 * this will trigger ClientOperation to use non-buffered stream so 107 * we can abort operation 108 */ 109 op.continueOperation(true, false); 110 111 readResponseHeaders(op.getReceivedHeader()); 112 113 InputStream is = op.openInputStream(); 114 readResponse(is); 115 is.close(); 116 117 op.close(); 118 119 mResponseCode = op.getResponseCode(); 120 } catch (IOException e) { 121 mResponseCode = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 122 123 throw e; 124 } 125 } 126 127 protected void executePut(ClientSession session, byte[] body) throws IOException { 128 Operation op = null; 129 130 mHeaderSet.setHeader(HeaderSet.LENGTH, Long.valueOf(body.length)); 131 132 try { 133 op = session.put(mHeaderSet); 134 135 DataOutputStream out = op.openDataOutputStream(); 136 out.write(body); 137 out.close(); 138 139 readResponseHeaders(op.getReceivedHeader()); 140 141 op.close(); 142 mResponseCode = op.getResponseCode(); 143 } catch (IOException e) { 144 mResponseCode = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 145 146 throw e; 147 } 148 } 149 150 final public boolean isSuccess() { 151 return (mResponseCode == ResponseCodes.OBEX_HTTP_OK); 152 } 153 154 protected void readResponse(InputStream stream) throws IOException { 155 /* nothing here by default */ 156 } 157 158 protected void readResponseHeaders(HeaderSet headerset) { 159 /* nothing here by default */ 160 } 161 } 162