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
26 package com.intel.bluetooth.emu;
27
28 import java.io.IOException;
29 import java.util.Enumeration;
30 import java.util.Hashtable;
31 import java.util.LinkedList;
32 import java.util.List;
33 import java.util.Queue;
34 import java.util.Vector;
35
36 import javax.bluetooth.BluetoothConnectionException;
37
38 import com.intel.bluetooth.DebugLog;
39 import com.intel.bluetooth.RemoteDeviceHelper;
40
41
42
43 class Device {
44
45 private boolean isReleased = false;
46
47 private DeviceDescriptor descriptor;
48
49 private DeviceSDP sdp;
50
51 private Hashtable<String, String> servicesOpen = new Hashtable<String, String>();
52
53 private Vector<ServiceListener> serviceListeners;
54
55 private Object serviceNotification = new Object();
56
57 private Hashtable<Long, ConnectionBuffer> connections = new Hashtable<Long, ConnectionBuffer>();
58
59 private Queue<DeviceCommand> commandQueue = new LinkedList<DeviceCommand>();
60
61 private long lastEvent = System.currentTimeMillis();
62
63 Device(DeviceDescriptor descriptor) {
64 this.descriptor = descriptor;
65 this.serviceListeners = new Vector<ServiceListener>();
66 }
67
68 DeviceDescriptor getDescriptor() {
69 return this.descriptor;
70 }
71
72 boolean isHasServices() {
73 return !servicesOpen.isEmpty();
74 }
75
76 boolean isListening() {
77 return !serviceListeners.isEmpty();
78 }
79
80 Long[] getConnectedTo() {
81 List<Long> connectedTo = new Vector<Long>();
82 synchronized (connections) {
83 for (Enumeration<ConnectionBuffer> iterator = connections.elements(); iterator.hasMoreElements();) {
84 ConnectionBuffer c = (ConnectionBuffer) iterator.nextElement();
85 if (!c.isServerSide()) {
86 connectedTo.add(new Long(c.getRemoteAddress()));
87 }
88
89 }
90 }
91 return connectedTo.toArray(new Long[connectedTo.size()]);
92 }
93
94 synchronized DeviceSDP getDeviceSDP(boolean create) {
95 if (create && (sdp == null)) {
96 sdp = new DeviceSDP(descriptor.getAddress());
97 }
98 return sdp;
99 }
100
101 void openService(String portID) {
102 servicesOpen.put(portID, portID);
103 }
104
105 void closeService(String portID) {
106 servicesOpen.remove(portID);
107 ServiceListener sl;
108 while ((sl = removeServiceListener(portID)) != null) {
109 sl.close();
110 }
111 }
112
113 ServiceListener createServiceListener(String portID) {
114 ServiceListener sl = new ServiceListener(portID);
115 synchronized (serviceListeners) {
116 serviceListeners.addElement(sl);
117 }
118 return sl;
119 }
120
121 private ServiceListener removeServiceListener(String portID) {
122 ServiceListener sl = null;
123 synchronized (serviceListeners) {
124 for (Enumeration<ServiceListener> iterator = serviceListeners.elements(); iterator.hasMoreElements();) {
125 ServiceListener s = (ServiceListener) iterator.nextElement();
126 if (s.getPortID().equals(portID)) {
127 serviceListeners.removeElement(s);
128 sl = s;
129 break;
130 }
131 }
132 }
133 return sl;
134 }
135
136 void serviceListenerAccepting(String portID) {
137 synchronized (serviceNotification) {
138 serviceNotification.notifyAll();
139 }
140 }
141
142 ServiceListener connectService(String portID, long timeout) throws IOException {
143 if (servicesOpen.get(portID) == null) {
144 return null;
145 }
146 ServiceListener sl = removeServiceListener(portID);
147 long endOfDellay = System.currentTimeMillis() + timeout;
148 while ((sl == null) && (timeout > 0)) {
149 long timeleft = endOfDellay - System.currentTimeMillis();
150 if (timeleft <= 0) {
151 throw new BluetoothConnectionException(BluetoothConnectionException.TIMEOUT, "Service " + portID
152 + " not accepting");
153 }
154 try {
155 synchronized (serviceNotification) {
156 serviceNotification.wait(timeleft);
157 }
158 } catch (InterruptedException e) {
159 break;
160 }
161 if (servicesOpen.get(portID) == null) {
162 break;
163 }
164 sl = removeServiceListener(portID);
165 }
166 return sl;
167 }
168
169 void addConnectionBuffer(long connectionId, ConnectionBuffer c) {
170 synchronized (connections) {
171 connections.put(new Long(connectionId), c);
172 }
173 }
174
175 ConnectionBuffer getConnectionBuffer(long connectionId) {
176 return (ConnectionBuffer) connections.get(new Long(connectionId));
177 }
178
179 ConnectionBuffer getConnectionBuffer(long remoteAddress, String portID) {
180 synchronized (connections) {
181 for (Enumeration<ConnectionBuffer> iterator = connections.elements(); iterator.hasMoreElements();) {
182 ConnectionBuffer c = (ConnectionBuffer) iterator.nextElement();
183 if ((c.remoteAddress == remoteAddress) && (c.getPortID().equals(portID))) {
184 return c;
185 }
186 }
187 connections.clear();
188 }
189 return null;
190 }
191
192 void closeConnection(long connectionId) throws IOException {
193 ConnectionBuffer c;
194 synchronized (connections) {
195 c = connections.remove(new Long(connectionId));
196 }
197 if (c == null) {
198 throw new IOException("No such connection " + connectionId);
199 }
200 c.close();
201 }
202
203 void setDevicePower(boolean on) {
204 this.descriptor.setPoweredOn(on);
205 if (!on) {
206 close();
207 }
208 putCommand(new DeviceCommand(DeviceCommand.DeviceCommandType.chagePowerState, new Boolean(on)));
209 }
210
211 void putCommand(DeviceCommand command) {
212 synchronized (commandQueue) {
213 commandQueue.add(command);
214 commandQueue.notifyAll();
215 }
216 }
217
218 DeviceCommand pollCommand() {
219 lastEvent = System.currentTimeMillis();
220 DeviceCommand command = null;
221 synchronized (commandQueue) {
222 while (command == null && (!isReleased)) {
223 command = commandQueue.poll();
224 if (command == null) {
225 try {
226 commandQueue.wait(DeviceManagerServiceImpl.configuration.getKeepAliveSeconds() * 1000);
227 if ((!isReleased) && commandQueue.isEmpty()) {
228 command = DeviceCommand.keepAliveCommand;
229 break;
230 }
231 } catch (InterruptedException e) {
232 break;
233 }
234 }
235 }
236 }
237 return command;
238 }
239
240 boolean isAlive() {
241 return System.currentTimeMillis() < (lastEvent + (DeviceManagerServiceImpl.configuration.getKeepAliveSeconds() + 7) * 1000);
242 }
243
244 void died() {
245 DebugLog.debug("device died", RemoteDeviceHelper.getBluetoothAddress(descriptor.getAddress()));
246 release();
247 }
248
249 void release() {
250 isReleased = true;
251 close();
252 }
253
254 void close() {
255 synchronized (commandQueue) {
256 commandQueue.notifyAll();
257 }
258 servicesOpen.clear();
259 for (Enumeration<ServiceListener> iterator = serviceListeners.elements(); iterator.hasMoreElements();) {
260 ServiceListener s = (ServiceListener) iterator.nextElement();
261 s.close();
262 }
263 serviceListeners.clear();
264 synchronized (connections) {
265 for (Enumeration<ConnectionBuffer> iterator = connections.elements(); iterator.hasMoreElements();) {
266 ConnectionBuffer c = (ConnectionBuffer) iterator.nextElement();
267 try {
268 c.close();
269 } catch (IOException e) {
270 }
271 }
272 connections.clear();
273 }
274 }
275 }