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
17package android.bluetooth.client.map;
18
19import java.io.DataOutputStream;
20import java.io.IOException;
21import java.io.InputStream;
22
23import javax.obex.ClientOperation;
24import javax.obex.ClientSession;
25import javax.obex.HeaderSet;
26import javax.obex.Operation;
27import javax.obex.ResponseCodes;
28
29abstract 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
85    public BluetoothMasRequest() {
86        mHeaderSet = new HeaderSet();
87    }
88
89    abstract public void execute(ClientSession session) throws IOException;
90
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
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
151    final public boolean isSuccess() {
152        return (mResponseCode == ResponseCodes.OBEX_HTTP_OK);
153    }
154
155    protected void readResponse(InputStream stream) throws IOException {
156        /* nothing here by default */
157    }
158
159    protected void readResponseHeaders(HeaderSet headerset) {
160        /* nothing here by default */
161    }
162}
163