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