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.Hashtable;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Vector;
34
35 import javax.bluetooth.BluetoothConnectionException;
36 import javax.bluetooth.BluetoothStateException;
37 import javax.bluetooth.DiscoveryAgent;
38 import javax.bluetooth.ServiceRegistrationException;
39
40 import com.intel.bluetooth.DebugLog;
41 import com.intel.bluetooth.RemoteDeviceHelper;
42
43 public class DeviceManagerServiceImpl implements DeviceManagerService {
44
45 public static final int MAJOR_COMPUTER = 0x0100;
46
47 static final EmulatorConfiguration configuration;
48
49 private static Map<Long, Device> devices = new Hashtable<Long, Device>();
50
51 static {
52 configuration = new EmulatorConfiguration();
53 configuration.loadConfigFile();
54 }
55
56 public DeviceManagerServiceImpl() {
57 }
58
59 public void shutdown() {
60 synchronized (devices) {
61 for (Iterator<Device> iterator = devices.values().iterator(); iterator.hasNext();) {
62 Device device = iterator.next();
63 device.release();
64 }
65 devices.clear();
66 }
67 }
68
69 public DeviceDescriptor createNewDevice(String deviceID, String deviceAddress) throws BluetoothStateException {
70 synchronized (devices) {
71 long address = getNextAvailableBTAddress(deviceID, deviceAddress);
72
73 String name = configuration.getProperty(address, EmulatorConfiguration.deviceName);
74 if (name == null) {
75 name = configuration.getDeviceNamePrefix() + RemoteDeviceHelper.getBluetoothAddress(address);
76 }
77 int deviceClass = MAJOR_COMPUTER;
78 String cod = configuration.getProperty(address, EmulatorConfiguration.deviceClass);
79 if (cod != null) {
80 deviceClass = EmulatorConfiguration.valueToInt(cod);
81 }
82 DeviceDescriptor descriptor = new DeviceDescriptor(address, name, deviceClass);
83
84 if (!configuration.isDeviceDiscoverable()) {
85 descriptor.setDiscoverableMode(DiscoveryAgent.NOT_DISCOVERABLE);
86 }
87
88 devices.put(new Long(address), new Device(descriptor));
89 return descriptor;
90 }
91 }
92
93 public EmulatorConfiguration getEmulatorConfiguration(long localAddress) {
94 return configuration.clone(localAddress);
95 }
96
97 public void releaseDevice(long address) {
98 Device device;
99 synchronized (devices) {
100 device = (Device) devices.remove(new Long(address));
101 }
102 if (device != null) {
103 device.release();
104 }
105 }
106
107 public DeviceCommand pollCommand(long address) {
108 Device device = getDevice(address);
109 if (device == null) {
110 throw new RuntimeException("No such device " + RemoteDeviceHelper.getBluetoothAddress(address));
111 }
112 return device.pollCommand();
113 }
114
115 static Device getDevice(long address) {
116 Device d = ((Device) devices.get(new Long(address)));
117 if ((d != null) && (!d.isAlive())) {
118 synchronized (devices) {
119 devices.remove(new Long(address));
120 }
121 d.died();
122 return null;
123 }
124 return d;
125 }
126
127 private Device getActiveDevice(long address) {
128 Device d = getDevice(address);
129 if ((d != null) && (!d.getDescriptor().isPoweredOn())) {
130 return null;
131 } else {
132 return d;
133 }
134 }
135
136 public DeviceDescriptor getDeviceDescriptor(long address) {
137 Device device = getDevice(address);
138 if (device == null) {
139 throw new RuntimeException("No such device " + RemoteDeviceHelper.getBluetoothAddress(address));
140 }
141 return device.getDescriptor();
142 }
143
144 private DeviceSDP getDeviceSDP(long address) {
145 Device device = getActiveDevice(address);
146 if (device == null) {
147 return null;
148 }
149 return device.getDeviceSDP(false);
150 }
151
152 public static List<MonitorDevice> getMonitorDevices() {
153 Vector<MonitorDevice> monitorDevices = new Vector<MonitorDevice>();
154 synchronized (devices) {
155 for (Iterator<Device> iterator = devices.values().iterator(); iterator.hasNext();) {
156 Device device = iterator.next();
157 if (!device.isAlive()) {
158 iterator.remove();
159 device.died();
160 continue;
161 }
162 isDiscoverable(device.getDescriptor());
163 monitorDevices.add(new MonitorDevice(device));
164 }
165 }
166 return monitorDevices;
167 }
168
169 public DeviceDescriptor[] getDiscoveredDevices(long address) {
170 Vector<DeviceDescriptor> discoveredDevice = new Vector<DeviceDescriptor>();
171 synchronized (devices) {
172 for (Iterator<Device> iterator = devices.values().iterator(); iterator.hasNext();) {
173 Device device = iterator.next();
174 if (!device.isAlive()) {
175 iterator.remove();
176 device.died();
177 continue;
178 }
179 if (device.getDescriptor().getAddress() == address) {
180 continue;
181 }
182 if (isDiscoverable(device.getDescriptor())) {
183 discoveredDevice.addElement(device.getDescriptor());
184 }
185 }
186 }
187 return (DeviceDescriptor[]) discoveredDevice.toArray(new DeviceDescriptor[discoveredDevice.size()]);
188 }
189
190 private static boolean isDiscoverable(DeviceDescriptor device) {
191 if (!device.isPoweredOn()) {
192 return false;
193 }
194 int discoverableMode = device.getDiscoverableMode();
195 switch (discoverableMode) {
196 case DiscoveryAgent.NOT_DISCOVERABLE:
197 return false;
198 case DiscoveryAgent.GIAC:
199 return true;
200 case DiscoveryAgent.LIAC:
201 if (device.getLimitedDiscoverableStart() + configuration.getDurationLIAC() * 1000 * 60 < System
202 .currentTimeMillis()) {
203 DebugLog.debug(RemoteDeviceHelper.getBluetoothAddress(device.getAddress())
204 + " LIAC -> NOT_DISCOVERABLE");
205 device.setDiscoverableMode(DiscoveryAgent.NOT_DISCOVERABLE);
206 return false;
207 } else {
208 return true;
209 }
210 default:
211
212 return true;
213 }
214 }
215
216 public boolean isLocalDevicePowerOn(long localAddress) {
217 return getDeviceDescriptor(localAddress).isPoweredOn();
218 }
219
220 public void setLocalDevicePower(long localAddress, boolean on) {
221 Device device = getDevice(localAddress);
222 if (device == null) {
223 throw new RuntimeException("No such device " + RemoteDeviceHelper.getBluetoothAddress(localAddress));
224 }
225 device.setDevicePower(on);
226 }
227
228 public int getLocalDeviceDiscoverable(long localAddress) {
229 DeviceDescriptor dd = getDeviceDescriptor(localAddress);
230 if (!dd.isPoweredOn()) {
231 return DiscoveryAgent.NOT_DISCOVERABLE;
232 }
233
234 isDiscoverable(dd);
235 return dd.getDiscoverableMode();
236 }
237
238 public boolean setLocalDeviceDiscoverable(long localAddress, int mode) throws BluetoothStateException {
239 DeviceDescriptor dd = getDeviceDescriptor(localAddress);
240 if (!dd.isPoweredOn()) {
241 throw new BluetoothStateException("Device power is off");
242 }
243 DebugLog.debug(RemoteDeviceHelper.getBluetoothAddress(localAddress) + " setDiscoverableMode", EmulatorUtils
244 .discoverableModeString(mode));
245 dd.setDiscoverableMode(mode);
246 return true;
247 }
248
249 public void setLocalDeviceServiceClasses(long localAddress, int classOfDevice) {
250 DebugLog.debug(RemoteDeviceHelper.getBluetoothAddress(localAddress) + " setServiceClasses ", classOfDevice);
251 getDeviceDescriptor(localAddress).setDeviceClass(classOfDevice);
252 }
253
254 public String getRemoteDeviceFriendlyName(long address) throws IOException {
255 DeviceDescriptor dd = getDeviceDescriptor(address);
256 if (!dd.isPoweredOn()) {
257 throw new IOException("Remote device power is off");
258 }
259 return dd.getName();
260 }
261
262 private long getNextAvailableBTAddress(String deviceID, String deviceAddress) throws BluetoothStateException {
263 if (deviceID != null) {
264 long id = configuration.getFirstDeviceAddress() + Long.parseLong(deviceID);
265 if (getDevice(id) != null) {
266 throw new BluetoothStateException("Device already reserved "
267 + RemoteDeviceHelper.getBluetoothAddress(id));
268 }
269 return id;
270 } else if (deviceAddress != null) {
271 long address = RemoteDeviceHelper.getAddress(deviceAddress);
272 if (getDevice(address) != null) {
273 throw new BluetoothStateException("Device already reserved "
274 + RemoteDeviceHelper.getBluetoothAddress(address));
275 }
276 return address;
277 } else {
278 return EmulatorUtils.getNextAvailable(devices.keySet(), configuration.getFirstDeviceAddress(), 1);
279 }
280
281 }
282
283 public void updateServiceRecord(long address, long handle, ServicesDescriptor sdpData)
284 throws ServiceRegistrationException {
285 Device device = getActiveDevice(address);
286 if (device == null) {
287 throw new ServiceRegistrationException("No such device " + RemoteDeviceHelper.getBluetoothAddress(address));
288 }
289 DeviceSDP ds = device.getDeviceSDP(true);
290 ds.updateServiceRecord(handle, sdpData);
291 }
292
293 public void removeServiceRecord(long address, long handle) throws IOException {
294 DeviceSDP ds = getDeviceSDP(address);
295 if (ds != null) {
296 ds.removeServiceRecord(handle);
297 }
298 }
299
300 public long[] searchServices(long address, String[] uuidSet) {
301 if (getActiveDevice(address) == null) {
302 return null;
303 }
304 DeviceSDP ds = getDeviceSDP(address);
305 if (ds == null) {
306 return new long[0];
307 }
308 return ds.searchServices(uuidSet);
309 }
310
311 public byte[] getServicesRecordBinary(long address, long handle) throws IOException {
312 DeviceSDP ds = getDeviceSDP(address);
313 if (ds == null) {
314 throw new IOException("No such device " + RemoteDeviceHelper.getBluetoothAddress(address));
315 }
316 ServicesDescriptor sd = ds.getServicesDescriptor(handle);
317 if (sd == null) {
318 throw new IOException("No such service");
319 }
320 return sd.getSdpBinary();
321 }
322
323 public void rfOpenService(long localAddress, int channel) throws IOException {
324 openService(localAddress, ServiceListener.rfPrefix(channel));
325 }
326
327 public long rfAccept(long localAddress, int channel, boolean authenticate, boolean encrypt) throws IOException {
328 return accept(localAddress, ServiceListener.rfPrefix(channel), authenticate, encrypt, 0);
329 }
330
331 public long rfConnect(long localAddress, long remoteAddress, int channel, boolean authenticate, boolean encrypt,
332 int timeout) throws IOException {
333 return connect(localAddress, remoteAddress, ServiceListener.rfPrefix(channel), authenticate, encrypt, 0,
334 timeout);
335 }
336
337 public void rfCloseService(long address, int pcm) {
338 closeService(address, ServiceListener.rfPrefix(pcm));
339 }
340
341 public void l2OpenService(long localAddress, int pcm) throws IOException {
342 openService(localAddress, ServiceListener.l2Prefix(pcm));
343 }
344
345 public long l2Accept(long localAddress, int channel, boolean authenticate, boolean encrypt, int receiveMTU)
346 throws IOException {
347 return accept(localAddress, ServiceListener.l2Prefix(channel), authenticate, encrypt, receiveMTU);
348 }
349
350 public long l2Connect(long localAddress, long remoteAddress, int channel, boolean authenticate, boolean encrypt,
351 int receiveMTU, int timeout) throws IOException {
352 return connect(localAddress, remoteAddress, ServiceListener.l2Prefix(channel), authenticate, encrypt,
353 receiveMTU, timeout);
354 }
355
356 public void l2CloseService(long address, int channel) {
357 closeService(address, ServiceListener.l2Prefix(channel));
358 }
359
360 private long accept(long localAddress, String channelID, boolean authenticate, boolean encrypt, int receiveMTU)
361 throws IOException {
362 Device device;
363 if ((device = getActiveDevice(localAddress)) == null) {
364 throw new IOException("No such device " + RemoteDeviceHelper.getBluetoothAddress(localAddress));
365 }
366 ServiceListener sl = device.createServiceListener(channelID);
367 return sl.accept(device, authenticate, encrypt, receiveMTU);
368 }
369
370 private long connect(long localAddress, long remoteAddress, String portID, boolean authenticate, boolean encrypt,
371 int receiveMTU, int timeout) throws IOException {
372 Device remoteDevice = getActiveDevice(remoteAddress);
373 if (remoteDevice == null) {
374 throw new BluetoothConnectionException(BluetoothConnectionException.FAILED_NOINFO, "No such device "
375 + RemoteDeviceHelper.getBluetoothAddress(remoteAddress));
376 }
377 Device localDevice = getActiveDevice(localAddress);
378 if (localDevice == null) {
379 throw new BluetoothConnectionException(BluetoothConnectionException.FAILED_NOINFO, "No such device "
380 + RemoteDeviceHelper.getBluetoothAddress(localAddress));
381 }
382 if (localDevice.getConnectionBuffer(remoteAddress, portID) != null) {
383 throw new BluetoothConnectionException(BluetoothConnectionException.FAILED_NOINFO,
384 "Already connected to the same port " + portID + " on "
385 + RemoteDeviceHelper.getBluetoothAddress(remoteAddress));
386 }
387 ServiceListener sl = remoteDevice.connectService(portID, timeout);
388 if (sl == null) {
389 throw new BluetoothConnectionException(BluetoothConnectionException.UNKNOWN_PSM, "No such service "
390 + portID);
391 }
392 return sl.connect(localDevice, authenticate, encrypt, receiveMTU, timeout);
393 }
394
395 public void connectionAccepted(long localAddress, long connectionId) throws IOException {
396 Device device;
397 if ((device = getActiveDevice(localAddress)) == null) {
398 throw new IOException("No such device " + RemoteDeviceHelper.getBluetoothAddress(localAddress));
399 }
400 ConnectionBuffer c = device.getConnectionBuffer(connectionId);
401 if (c == null) {
402 throw new IOException("No such connection " + connectionId);
403 }
404 c.accepted();
405 }
406
407 private void openService(long address, String channelID) throws IOException {
408 Device device = getActiveDevice(address);
409 if (device == null) {
410 throw new IOException("No such device " + RemoteDeviceHelper.getBluetoothAddress(address));
411 }
412 device.openService(channelID);
413 }
414
415 private void closeService(long address, String channelID) {
416 Device device = getDevice(address);
417 if (device == null) {
418 return;
419 }
420 device.closeService(channelID);
421 }
422
423 private ConnectionBuffer getConnectionBuffer(long localAddress, long connectionId) throws IOException {
424 Device localDevice = getActiveDevice(localAddress);
425 if (localDevice == null) {
426 throw new IOException("No such device " + RemoteDeviceHelper.getBluetoothAddress(localAddress));
427 }
428 ConnectionBuffer c = localDevice.getConnectionBuffer(connectionId);
429 if (c == null) {
430 throw new IOException("No such connection " + connectionId);
431 }
432 return c;
433 }
434
435 public long getRemoteAddress(long localAddress, long connectionId) throws IOException {
436 return getConnectionBuffer(localAddress, connectionId).getRemoteAddress();
437 }
438
439 public void rfWrite(long localAddress, long connectionId, byte[] b) throws IOException {
440 ((ConnectionBufferRFCOMM) getConnectionBuffer(localAddress, connectionId)).rfWrite(b);
441 }
442
443 public void rfFlush(long localAddress, long connectionId) throws IOException {
444 ((ConnectionBufferRFCOMM) getConnectionBuffer(localAddress, connectionId)).rfFlush();
445 }
446
447 public int rfAvailable(long localAddress, long connectionId) throws IOException {
448 return ((ConnectionBufferRFCOMM) getConnectionBuffer(localAddress, connectionId)).rfAvailable();
449 }
450
451 public byte[] rfRead(long localAddress, long connectionId, int len) throws IOException {
452 return ((ConnectionBufferRFCOMM) getConnectionBuffer(localAddress, connectionId)).rfRead(len);
453 }
454
455 public void closeConnection(long localAddress, long connectionId) throws IOException {
456 Device localDevice = getDevice(localAddress);
457 if (localDevice == null) {
458 throw new IOException("No such device " + RemoteDeviceHelper.getBluetoothAddress(localAddress));
459 }
460 localDevice.closeConnection(connectionId);
461 }
462
463 public int getSecurityOpt(long localAddress, long connectionId, int expected) throws IOException {
464 return ((ConnectionBuffer) getConnectionBuffer(localAddress, connectionId)).getSecurityOpt(expected);
465 }
466
467 public boolean encrypt(long localAddress, long connectionId, long remoteAddress, boolean on) throws IOException {
468 return ((ConnectionBuffer) getConnectionBuffer(localAddress, connectionId)).encrypt(remoteAddress, on);
469 }
470
471 public int l2RemoteDeviceReceiveMTU(long localAddress, long connectionId) throws IOException {
472 return ((ConnectionBufferL2CAP) getConnectionBuffer(localAddress, connectionId)).getRemoteReceiveMTU();
473 }
474
475 public boolean l2Ready(long localAddress, long connectionId) throws IOException {
476 return ((ConnectionBufferL2CAP) getConnectionBuffer(localAddress, connectionId)).ready();
477 }
478
479 public byte[] l2Receive(long localAddress, long connectionId, int len) throws IOException {
480 return ((ConnectionBufferL2CAP) getConnectionBuffer(localAddress, connectionId)).receive(len);
481 }
482
483 public void l2Send(long localAddress, long connectionId, byte[] data) throws IOException {
484 ((ConnectionBufferL2CAP) getConnectionBuffer(localAddress, connectionId)).send(data);
485 }
486 }