1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package com.intel.bluetooth;
26
27 import java.io.IOException;
28 import java.util.Enumeration;
29 import java.util.Hashtable;
30 import java.util.Vector;
31
32 import javax.bluetooth.BluetoothStateException;
33 import javax.bluetooth.DataElement;
34 import javax.bluetooth.ServiceRecord;
35 import javax.bluetooth.ServiceRegistrationException;
36 import javax.microedition.io.Connection;
37
38
39
40
41 abstract class BluetoothConnectionNotifierBase implements Connection, BluetoothConnectionNotifierServiceRecordAccess {
42
43 private static Hashtable stackConnections = new Hashtable();
44
45 protected BluetoothStack bluetoothStack;
46
47 protected volatile long handle;
48
49 protected ServiceRecordImpl serviceRecord;
50
51 protected boolean closed;
52
53 protected int securityOpt;
54
55 static void shutdownConnections(BluetoothStack bluetoothStack) {
56 Vector connections;
57 synchronized (stackConnections) {
58 connections = (Vector) stackConnections.get(bluetoothStack);
59 }
60 if (connections == null) {
61 return;
62 }
63 Vector c2shutdown = new Vector();
64 c2shutdown = Utils.clone(connections.elements());
65 for (Enumeration en = c2shutdown.elements(); en.hasMoreElements();) {
66 BluetoothConnectionNotifierBase c = (BluetoothConnectionNotifierBase) en.nextElement();
67 try {
68 c.shutdown();
69 } catch (IOException e) {
70 DebugLog.debug("connection shutdown", e);
71 }
72 }
73 }
74
75 protected BluetoothConnectionNotifierBase(BluetoothStack bluetoothStack, BluetoothConnectionNotifierParams params)
76 throws BluetoothStateException, Error {
77 this.bluetoothStack = bluetoothStack;
78 this.closed = false;
79 if (params.name == null) {
80 throw new NullPointerException("Service name is null");
81 }
82
83
84
85 this.serviceRecord = new ServiceRecordImpl(this.bluetoothStack, null, 0);
86 }
87
88 protected void connectionCreated() {
89 Vector connections;
90 synchronized (stackConnections) {
91 connections = (Vector) stackConnections.get(this.bluetoothStack);
92 if (connections == null) {
93 connections = new Vector();
94 stackConnections.put(this.bluetoothStack, connections);
95 }
96 }
97 connections.addElement(this);
98 }
99
100 protected abstract void stackServerClose(long handle) throws IOException;
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 public void close() throws IOException {
118 if (!closed) {
119 shutdown();
120 }
121 }
122
123 public void shutdown() throws IOException {
124 closed = true;
125 if (handle != 0) {
126 DebugLog.debug("closing ConnectionNotifier", handle);
127 Vector connections;
128 synchronized (stackConnections) {
129 connections = (Vector) stackConnections.get(this.bluetoothStack);
130 }
131 connections.removeElement(this);
132 long synchronizedHandle;
133 synchronized (this) {
134 synchronizedHandle = handle;
135 handle = 0;
136 }
137 if (synchronizedHandle != 0) {
138
139 ServiceRecordsRegistry.unregister(serviceRecord);
140
141 if ((serviceRecord.deviceServiceClasses != 0)
142 && ((bluetoothStack.getFeatureSet() & BluetoothStack.FEATURE_SET_DEVICE_SERVICE_CLASSES) != 0)) {
143 bluetoothStack.setLocalDeviceServiceClasses(ServiceRecordsRegistry.getDeviceServiceClasses());
144 }
145
146 stackServerClose(synchronizedHandle);
147 }
148 }
149 }
150
151
152
153
154
155
156 public ServiceRecord getServiceRecord() {
157 if (closed) {
158 throw new IllegalArgumentException("ConnectionNotifier is closed");
159 }
160 ServiceRecordsRegistry.register(this, serviceRecord);
161 return serviceRecord;
162 }
163
164 protected void validateServiceRecord(ServiceRecord srvRecord) {
165 DataElement protocolDescriptor = srvRecord.getAttributeValue(BluetoothConsts.ProtocolDescriptorList);
166 if ((protocolDescriptor == null) || (protocolDescriptor.getDataType() != DataElement.DATSEQ)) {
167 throw new IllegalArgumentException("ProtocolDescriptorList is mandatory");
168 }
169
170 DataElement serviceClassIDList = srvRecord.getAttributeValue(BluetoothConsts.ServiceClassIDList);
171 if ((serviceClassIDList == null) || (serviceClassIDList.getDataType() != DataElement.DATSEQ)
172 || serviceClassIDList.getSize() == 0) {
173 throw new IllegalArgumentException("ServiceClassIDList is mandatory");
174 }
175
176 boolean isL2CAPpresent = false;
177 for (Enumeration protocolsSeqEnum = (Enumeration) protocolDescriptor.getValue(); protocolsSeqEnum
178 .hasMoreElements();) {
179 DataElement elementSeq = (DataElement) protocolsSeqEnum.nextElement();
180 if (elementSeq.getDataType() == DataElement.DATSEQ) {
181 Enumeration elementSeqEnum = (Enumeration) elementSeq.getValue();
182 if (elementSeqEnum.hasMoreElements()) {
183 DataElement protocolElement = (DataElement) elementSeqEnum.nextElement();
184 if ((protocolElement.getDataType() == DataElement.UUID)
185 && (BluetoothConsts.L2CAP_PROTOCOL_UUID.equals(protocolElement.getValue()))) {
186 isL2CAPpresent = true;
187 break;
188 }
189 }
190 }
191 }
192 if (!isL2CAPpresent) {
193 throw new IllegalArgumentException("L2CAP UUID is mandatory in ProtocolDescriptorList");
194 }
195 }
196
197 protected abstract void updateStackServiceRecord(ServiceRecordImpl serviceRecord, boolean acceptAndOpen)
198 throws ServiceRegistrationException;
199
200
201
202
203
204
205 public void updateServiceRecord(boolean acceptAndOpen) throws ServiceRegistrationException {
206 if (serviceRecord.attributeUpdated || (!acceptAndOpen)) {
207 try {
208 validateServiceRecord(this.serviceRecord);
209 } catch (IllegalArgumentException e) {
210 if (acceptAndOpen) {
211 throw new ServiceRegistrationException(e.getMessage());
212 } else {
213 throw e;
214 }
215 }
216 try {
217 updateStackServiceRecord(serviceRecord, acceptAndOpen);
218 } finally {
219 serviceRecord.attributeUpdated = false;
220 }
221 }
222 if ((serviceRecord.deviceServiceClasses != serviceRecord.deviceServiceClassesRegistered)
223 && ((bluetoothStack.getFeatureSet() & BluetoothStack.FEATURE_SET_DEVICE_SERVICE_CLASSES) != 0)) {
224
225 bluetoothStack.setLocalDeviceServiceClasses(ServiceRecordsRegistry.getDeviceServiceClasses());
226
227 serviceRecord.deviceServiceClassesRegistered = serviceRecord.deviceServiceClasses;
228 }
229 }
230 }