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_PARAMETER_MASK = 0x10; 47 protected static final byte OAP_TAGID_FOLDER_LISTING_SIZE = 0x11; 48 protected static final byte OAP_TAGID_MESSAGES_LISTING_SIZE = 0x12; 49 protected static final byte OAP_TAGID_SUBJECT_LENGTH = 0x13; 50 protected static final byte OAP_TAGID_CHARSET = 0x14; 51 protected static final byte OAP_TAGID_STATUS_INDICATOR = 0x17; 52 protected static final byte OAP_TAGID_STATUS_VALUE = 0x18; 53 protected static final byte OAP_TAGID_MSE_TIME = 0x19; 54 55 protected static byte NOTIFICATION_ON = 0x01; 56 protected static byte NOTIFICATION_OFF = 0x00; 57 58 protected static byte ATTACHMENT_ON = 0x01; 59 protected static byte ATTACHMENT_OFF = 0x00; 60 61 protected static byte CHARSET_NATIVE = 0x00; 62 protected static byte CHARSET_UTF8 = 0x01; 63 64 protected static byte STATUS_INDICATOR_READ = 0x00; 65 protected static byte STATUS_INDICATOR_DELETED = 0x01; 66 67 protected static byte STATUS_NO = 0x00; 68 protected static byte STATUS_YES = 0x01; 69 70 protected static byte TRANSPARENT_OFF = 0x00; 71 protected static byte TRANSPARENT_ON = 0x01; 72 73 protected static byte RETRY_OFF = 0x00; 74 protected static byte RETRY_ON = 0x01; 75 76 /* used for PUT requests which require filler byte */ 77 protected static final byte[] FILLER_BYTE = { 78 0x30 79 }; 80 81 protected HeaderSet mHeaderSet; 82 83 protected int mResponseCode; 84 BluetoothMasRequest()85 public BluetoothMasRequest() { 86 mHeaderSet = new HeaderSet(); 87 } 88 execute(ClientSession session)89 abstract public void execute(ClientSession session) throws IOException; 90 executeGet(ClientSession session)91 protected void executeGet(ClientSession session) throws IOException { 92 ClientOperation op = null; 93 94 try { 95 op = (ClientOperation) session.get(mHeaderSet); 96 97 /* 98 * MAP spec does not explicitly require that GET request should be 99 * sent in single packet but for some reason PTS complains when 100 * final GET packet with no headers follows non-final GET with all 101 * headers. So this is workaround, at least temporary. TODO: check 102 * with PTS 103 */ 104 op.setGetFinalFlag(true); 105 106 /* 107 * this will trigger ClientOperation to use non-buffered stream so 108 * we can abort operation 109 */ 110 op.continueOperation(true, false); 111 112 readResponseHeaders(op.getReceivedHeader()); 113 114 InputStream is = op.openInputStream(); 115 readResponse(is); 116 is.close(); 117 118 op.close(); 119 120 mResponseCode = op.getResponseCode(); 121 } catch (IOException e) { 122 mResponseCode = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 123 124 throw e; 125 } 126 } 127 executePut(ClientSession session, byte[] body)128 protected void executePut(ClientSession session, byte[] body) throws IOException { 129 Operation op = null; 130 131 mHeaderSet.setHeader(HeaderSet.LENGTH, Long.valueOf(body.length)); 132 133 try { 134 op = session.put(mHeaderSet); 135 136 DataOutputStream out = op.openDataOutputStream(); 137 out.write(body); 138 out.close(); 139 140 readResponseHeaders(op.getReceivedHeader()); 141 142 op.close(); 143 mResponseCode = op.getResponseCode(); 144 } catch (IOException e) { 145 mResponseCode = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 146 147 throw e; 148 } 149 } 150 isSuccess()151 final public boolean isSuccess() { 152 return (mResponseCode == ResponseCodes.OBEX_HTTP_OK); 153 } 154 readResponse(InputStream stream)155 protected void readResponse(InputStream stream) throws IOException { 156 /* nothing here by default */ 157 } 158 readResponseHeaders(HeaderSet headerset)159 protected void readResponseHeaders(HeaderSet headerset) { 160 /* nothing here by default */ 161 } 162 } 163