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