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