View Javadoc

1   /**
2    *  BlueCove - Java library for Bluetooth
3    *  Copyright (C) 2008 Michael Lifshits
4    *  Copyright (C) 2008 Vlad Skarzhevskyy
5    *
6    *  Licensed to the Apache Software Foundation (ASF) under one
7    *  or more contributor license agreements.  See the NOTICE file
8    *  distributed with this work for additional information
9    *  regarding copyright ownership.  The ASF licenses this file
10   *  to you under the Apache License, Version 2.0 (the
11   *  "License"); you may not use this file except in compliance
12   *  with the License.  You may obtain a copy of the License at
13   *
14   *    http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing,
17   *  software distributed under the License is distributed on an
18   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19   *  KIND, either express or implied.  See the License for the
20   *  specific language governing permissions and limitations
21   *  under the License.
22   *
23   *  @author vlads
24   *  @version $Id: Device.java 2535 2008-12-09 23:50:16Z skarzhevskyy $
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 }