com.intel.bluetooth.SelectServiceHandler Maven / Gradle / Ivy
/**
* BlueCove - Java library for Bluetooth
* Copyright (C) 2006-2007 Vlad Skarzhevskyy
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @version $Id: SelectServiceHandler.java 918 2007-08-14 20:20:37Z skarzhevskyy $
*/
package com.intel.bluetooth;
import java.util.Hashtable;
import java.util.Vector;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
/**
* Implementation of DiscoveryAgent.selectService().
*
*
* Your application should not use this class directly.
*
* @author vlads
*
*/
public class SelectServiceHandler implements DiscoveryListener {
private DiscoveryAgent agent;
private Object inquiryCompletedEvent = new Object();
private Object serviceSearchCompletedEvent = new Object();
private Hashtable devicesProcessed = new Hashtable();
private Vector serviceSearchDeviceQueue = new Vector();
UUID uuid;
private ServiceRecord servRecordDiscovered;
public SelectServiceHandler(DiscoveryAgent agent) {
this.agent = agent;
}
/**
* Attempts to locate a service that contains uuid
in
* the ServiceClassIDList of its service record. This
* method will return a string that may be used in
* Connector.open()
to establish a connection to the
* service. How the service is selected if there are multiple services
* with uuid
and which devices to
* search is implementation dependent.
*
* @see ServiceRecord#NOAUTHENTICATE_NOENCRYPT
* @see ServiceRecord#AUTHENTICATE_NOENCRYPT
* @see ServiceRecord#AUTHENTICATE_ENCRYPT
*
* @param uuid the UUID to search for in the ServiceClassIDList
*
* @param security specifies the security requirements for a connection
* to this service; must be one of
* ServiceRecord.NOAUTHENTICATE_NOENCRYPT
,
* ServiceRecord.AUTHENTICATE_NOENCRYPT
, or
* ServiceRecord.AUTHENTICATE_ENCRYPT
*
* @param master determines if this client must be the master of the
* connection; true
if the client must be the master;
* false
if the client can be the master or the slave
*
* @return the connection string used to connect to the service
* with a UUID of uuid
; or null
if no
* service could be found with a UUID of uuid
in the
* ServiceClassIDList
*
* @exception BluetoothStateException if the Bluetooth system cannot
* start the request due to the current state of the Bluetooth system
*
* @exception NullPointerException if uuid
is
* null
*
* @exception IllegalArgumentException if security
is
* not ServiceRecord.NOAUTHENTICATE_NOENCRYPT
,
* ServiceRecord.AUTHENTICATE_NOENCRYPT
, or
* ServiceRecord.AUTHENTICATE_ENCRYPT
*/
public String selectService(UUID uuid, int security, boolean master) throws BluetoothStateException {
if (uuid == null) {
throw new NullPointerException("uuid is null");
}
switch (security) {
case ServiceRecord.NOAUTHENTICATE_NOENCRYPT:
case ServiceRecord.AUTHENTICATE_NOENCRYPT:
case ServiceRecord.AUTHENTICATE_ENCRYPT:
break;
default:
throw new IllegalArgumentException();
}
RemoteDevice[] devs = agent.retrieveDevices(DiscoveryAgent.PREKNOWN);
for (int i = 0; (devs != null) && (i < devs.length); i++) {
ServiceRecord sr = findServiceOnDevice(uuid, devs[i]);
if (sr != null) {
return sr.getConnectionURL(security, master);
}
}
devs = agent.retrieveDevices(DiscoveryAgent.CACHED);
for (int i = 0; (devs != null) && (i < devs.length); i++) {
ServiceRecord sr = findServiceOnDevice(uuid, devs[i]);
if (sr != null) {
return sr.getConnectionURL(security, master);
}
}
this.uuid = uuid;
ParallelSearchServicesThread t = new ParallelSearchServicesThread();
t.start();
synchronized (inquiryCompletedEvent) {
if (!agent.startInquiry(DiscoveryAgent.GIAC, this)) {
return null;
}
try {
inquiryCompletedEvent.wait();
} catch (InterruptedException e) {
return null;
}
agent.cancelInquiry(this);
}
if ((servRecordDiscovered == null) && (!t.processedAll())) {
try {
t.join();
} catch (InterruptedException e) {
return null;
}
}
t.interrupt();
if (servRecordDiscovered != null) {
return servRecordDiscovered.getConnectionURL(security, master);
}
return null;
}
private class ParallelSearchServicesThread extends Thread {
boolean stoped = false;
int processedNext = 0;
int processedSize = 0;
boolean processedAll() {
return (processedNext == serviceSearchDeviceQueue.size());
}
public void interrupt() {
stoped = true;
super.interrupt();
}
public void run() {
mainLoop:
while ((!stoped) && (servRecordDiscovered == null)) {
synchronized (serviceSearchDeviceQueue) {
if (processedSize == serviceSearchDeviceQueue.size()) {
try {
serviceSearchDeviceQueue.wait();
} catch (InterruptedException e) {
return;
}
}
processedSize = serviceSearchDeviceQueue.size();
}
for (int i = processedNext; i < processedSize; i ++) {
RemoteDevice btDevice = (RemoteDevice)serviceSearchDeviceQueue.elementAt(i);
if (findServiceOnDevice(uuid, btDevice) != null) {
break mainLoop;
}
}
processedNext = processedSize + 1;
}
}
}
private ServiceRecord findServiceOnDevice(UUID uuid, RemoteDevice device) {
if (devicesProcessed.containsKey(device)) {
return null;
}
devicesProcessed.put(device, device);
DebugLog.debug("searchServices on ", device);
synchronized (serviceSearchCompletedEvent) {
try {
agent.searchServices(null, new UUID[]{uuid}, device, this);
} catch (BluetoothStateException e) {
DebugLog.error("searchServices", e);
}
try {
serviceSearchCompletedEvent.wait();
} catch (InterruptedException e) {
return null;
}
}
return servRecordDiscovered;
}
public void deviceDiscovered(final RemoteDevice btDevice, DeviceClass cod) {
if (devicesProcessed.containsKey(btDevice)) {
return;
}
synchronized (serviceSearchDeviceQueue) {
serviceSearchDeviceQueue.add(btDevice);
serviceSearchDeviceQueue.notifyAll();
}
}
public void inquiryCompleted(int discType) {
synchronized (inquiryCompletedEvent) {
inquiryCompletedEvent.notifyAll();
}
}
public void serviceSearchCompleted(int transID, int respCode) {
synchronized (serviceSearchCompletedEvent) {
serviceSearchCompletedEvent.notifyAll();
}
}
public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
if ((servRecord.length > 0 ) && (servRecordDiscovered == null)) {
servRecordDiscovered = servRecord[0];
synchronized (inquiryCompletedEvent) {
inquiryCompletedEvent.notifyAll();
}
}
}
}