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