Direct-BT  2.3.1
Direct-BT - Direct Bluetooth Programming.
DBTAdapter.java
Go to the documentation of this file.
1 /**
2  * Author: Sven Gothel <sgothel@jausoft.com>
3  * Copyright (c) 2020 Gothel Software e.K.
4  * Copyright (c) 2020 ZAFENA AB
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 package jau.direct_bt;
27 
28 import java.lang.ref.WeakReference;
29 import java.util.ArrayList;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.concurrent.atomic.AtomicBoolean;
33 import java.util.concurrent.atomic.AtomicInteger;
34 import java.util.concurrent.atomic.AtomicReference;
35 
40 import org.direct_bt.BTAdapter;
41 import org.direct_bt.BTDevice;
43 import org.direct_bt.BTGattChar;
44 import org.direct_bt.BTGattDesc;
46 import org.direct_bt.BTManager;
47 import org.direct_bt.BTObject;
48 import org.direct_bt.BTType;
49 import org.direct_bt.BTUtils;
51 import org.direct_bt.EUI48;
56 import org.direct_bt.ScanType;
57 
58 public class DBTAdapter extends DBTObject implements BTAdapter
59 {
60  private static final boolean DEBUG = DBTManager.DEBUG;
61  /* pp */ static final boolean PRINT_DEVICE_LISTS = false;
62 
63  private static AtomicInteger globThreadID = new AtomicInteger(0);
64  private static int discoverTimeoutMS = 100;
65 
66  private final int dev_id;
67  /**
68  * The adapter's initially reported address by the system, which always reflects its public address, i.e. BDAddressType::BDADDR_LE_PUBLIC.
69  */
70  private final BDAddressAndType addressAndType;
71  private final String name;
72  /**
73  * Either the adapter's initially reported public address or a random address setup via HCI before scanning / discovery.
74  */
75  private final BDAddressAndType visibleAddressAndType;
76 
77  private final Object discoveryLock = new Object();
78  private final Object discoveredDevicesLock = new Object();
79 
80  private final AtomicBoolean isClosing = new AtomicBoolean(false);
81 
82  private final AtomicBoolean powered_state = new AtomicBoolean(false); // AdapterSettings
83  private final AtomicBoolean isDiscoverable = new AtomicBoolean(false); // AdapterSettings
84 
85  private final AtomicReference<ScanType> currentMetaScanType = new AtomicReference<ScanType>(ScanType.NONE); // AdapterStatusListener and powerdOff
86 
87  private final List<WeakReference<BTDevice>> discoveredDevices = new ArrayList<WeakReference<BTDevice>>();
88 
89  /* pp */ DBTAdapter(final long nativeInstance,
90  final byte byteAddress[/*6*/],
91  final byte byteAddressType,
92  final String name, final int dev_id)
93  {
94  super(nativeInstance, compHash(java.util.Arrays.hashCode(byteAddress), 31+byteAddressType));
95  this.dev_id = dev_id;
96  this.addressAndType = new BDAddressAndType(new EUI48(byteAddress), BDAddressType.get(byteAddressType));
97  this.name = name;
98  this.visibleAddressAndType = addressAndType;
99  addStatusListener(this.statusListener);
100  }
101 
102  @Override
103  public final BTManager getManager() { return DBTManager.getManager(); }
104 
105  @Override
106  public void close() {
107  final DBTManager mngr = (DBTManager)DBTManager.getManager();
108  if( !isValid() ) {
109  return;
110  }
111  if( !isClosing.compareAndSet(false, true) ) {
112  return;
113  }
114  // mute all listener first
116 
117  stopDiscovery();
118 
119  final List<BTDevice> devices = getDiscoveredDevices();
120  for(final Iterator<BTDevice> id = devices.iterator(); id.hasNext(); ) {
121  final DBTDevice d = (DBTDevice) id.next();
122  d.close();
123  }
124 
125  // done in native dtor: removeDevicesImpl();
126 
127  poweredOff();
128 
129  mngr.removeAdapter(this); // remove this instance from manager
130 
131  super.close();
132  }
133 
134  private final void poweredOff() {
135  powered_state.set(false);
136  currentMetaScanType.set(ScanType.NONE);
137  }
138 
139  @Override
140  public boolean equals(final Object obj)
141  {
142  if(this == obj) {
143  return true;
144  }
145  if (obj == null || !(obj instanceof DBTAdapter)) {
146  return false;
147  }
148  final DBTAdapter other = (DBTAdapter)obj;
149  return dev_id == other.dev_id && addressAndType.equals(other.addressAndType);
150  }
151 
152  @Override
153  public BDAddressAndType getAddressAndType() { return addressAndType; }
154 
155  @Override
156  public BDAddressAndType getVisibleAddressAndType() { return visibleAddressAndType; }
157 
158  @Override
159  public String getName() { return name; }
160 
161  @Override
162  public int getDevID() { return dev_id; }
163 
164  @Override
165  public BTType getBluetoothType() { return class_type(); }
166 
167  static BTType class_type() { return BTType.ADAPTER; }
168 
169  @Override
170  public BTDevice find(final String name, final BDAddressAndType addressAndType, final long timeoutMS) {
171  return findDeviceInCache(name, addressAndType);
172  }
173 
174  @Override
175  public BTDevice find(final String name, final BDAddressAndType addressAndType) {
176  return find(name, addressAndType, 0);
177  }
178 
179  @Override
180  public final boolean isDeviceWhitelisted(final BDAddressAndType addressAndType) { return isDeviceWhitelistedImpl(addressAndType.address.b, addressAndType.type.value); }
181  private final native boolean isDeviceWhitelistedImpl(final byte[] address, byte address_type);
182 
183  @Override
184  public boolean addDeviceToWhitelist(final BDAddressAndType addressAndType,
185  final HCIWhitelistConnectType ctype,
186  final short conn_interval_min, final short conn_interval_max,
187  final short conn_latency, final short timeout) {
188  return addDeviceToWhitelistImpl1(addressAndType.address.b, addressAndType.type.value, ctype.value,
189  conn_interval_min, conn_interval_max, conn_latency, timeout);
190  }
191  private native boolean addDeviceToWhitelistImpl1(final byte[] address, final byte address_type, final int ctype,
192  final short conn_interval_min, final short conn_interval_max,
193  final short conn_latency, final short timeout);
194 
195  @Override
196  public boolean addDeviceToWhitelist(final BDAddressAndType addressAndType,
197  final HCIWhitelistConnectType ctype) {
198  return addDeviceToWhitelistImpl2(addressAndType.address.b, addressAndType.type.value, ctype.value);
199  }
200  private native boolean addDeviceToWhitelistImpl2(final byte[] address, final byte address_type, final int ctype);
201 
202  @Override
203  public boolean removeDeviceFromWhitelist(final BDAddressAndType addressAndType) {
204  return removeDeviceFromWhitelistImpl(addressAndType.address.b, addressAndType.type.value);
205  }
206  private native boolean removeDeviceFromWhitelistImpl(final byte[] address, final byte address_type);
207 
208  /* Unsupported */
209 
210  @Override
211  public boolean getDiscoverable() { return isDiscoverable.get(); }
212 
213  @Override
214  public final ScanType getCurrentScanType() {
215  return currentMetaScanType.get();
216  }
217 
218  @Override
219  public String toString() {
220  if( !isValid() ) {
221  return "Adapter" + "\u271D" + "["+addressAndType+", '"+name+"', id "+dev_id+"]";
222  }
223  return toStringImpl();
224  }
225 
226  /* Native callbacks */
227 
228  /* Native functionality / properties */
229 
230  private native String toStringImpl();
231 
232  @Override
233  public native boolean setPowered(boolean value);
234 
235  @Override
236  public final HCIStatusCode reset() {
237  return HCIStatusCode.get( resetImpl() );
238  }
239  private native byte resetImpl();
240 
241  @Override
242  public native String getAlias();
243 
244  @Override
245  public native void setAlias(final String value);
246 
247  @Override
248  public native boolean setDiscoverable(boolean value);
249 
250  @Override
251  public final BTDevice connectDevice(final BDAddressAndType addressAndType) {
252  return connectDeviceImpl(addressAndType.address.b, addressAndType.type.value);
253  }
254  private native BTDevice connectDeviceImpl(byte[] address, byte addressType);
255 
256  @Override
257  public native boolean setPairable(boolean value);
258 
259  @Override
260  public boolean getPoweredState() { return powered_state.get(); }
261 
262  @Override
263  public final boolean isPowered() { return isValid() && isPoweredImpl(); }
264  public native boolean isPoweredImpl();
265 
266  @Override
267  public final boolean isSuspended() { return isValid() && isSuspendedImpl(); }
268  public native boolean isSuspendedImpl();
269 
270  @Override
271  public final boolean isValid() { return super.isValid() && isValidImpl(); }
272  public native boolean isValidImpl();
273 
274  /* internal */
275 
276  @Override
277  protected native void deleteImpl(long nativeInstance);
278 
279  @Override
280  public HCIStatusCode startDiscovery(final boolean keepAlive, final boolean le_scan_active) throws BTException {
281  return startDiscovery(keepAlive, le_scan_active, (short)24, (short)24, (byte)0);
282  }
283  @Override
284  public HCIStatusCode startDiscovery(final boolean keepAlive, final boolean le_scan_active,
285  final short le_scan_interval, final short le_scan_window,
286  final byte filter_policy) throws BTException {
287  synchronized( discoveryLock ) {
288  // Ignoring 'isDiscovering', as native implementation also handles change of 'keepAlive'.
289  // The discoveredDevices shall always get cleared.
290  removeDiscoveredDevicesImpl2j();
291  final HCIStatusCode res = HCIStatusCode.get( startDiscoveryImpl(keepAlive, le_scan_active, le_scan_interval, le_scan_window, filter_policy) ); // event callbacks will be generated by implementation
292  if( PRINT_DEVICE_LISTS || DEBUG ) {
293  BTUtils.fprintf_td(System.err, "BTAdapter::startDiscovery: res %s, %s", res, toString());
295  }
296  return res;
297  }
298  }
299  private native byte startDiscoveryImpl(final boolean keepAlive, final boolean le_scan_active,
300  final short le_scan_interval, final short le_scan_window,
301  final byte filter_policy) throws BTException;
302 
303  @Override
305  synchronized( discoveryLock ) {
306  // Ignoring 'isDiscovering', be consistent with startDiscovery
307  final HCIStatusCode res = HCIStatusCode.get( stopDiscoveryImpl() ); // event callbacks will be generated by implementation
308  if( PRINT_DEVICE_LISTS || DEBUG ) {
309  BTUtils.fprintf_td(System.err, "BTAdapter::stopDiscovery: res %s, %s", res, toString());
311  }
312  return res;
313  }
314  }
315  private native byte stopDiscoveryImpl() throws BTException;
316 
317  // std::vector<std::shared_ptr<direct_bt::HCIDevice>> discoveredDevices = adapter.getDiscoveredDevices();
318  private native List<BTDevice> getDiscoveredDevicesImpl();
319 
320  @Override
321  public int removeDiscoveredDevices() throws BTException {
322  final int cj = removeDiscoveredDevicesImpl2j();
323  final int cn = removeDiscoveredDevicesImpl1();
324  if( DEBUG ) {
325  if( cj != cn ) {
326  System.err.println("DBTAdapter::removeDevices: Unexpected discovered device count: Native "+cn+", callback "+cj);
327  }
328  }
329  return cn;
330  }
331  private native int removeDiscoveredDevicesImpl1() throws BTException;
332  private int removeDiscoveredDevicesImpl2j() {
333  synchronized(discoveredDevicesLock) {
334  final int n = discoveredDevices.size();
335  discoveredDevices.clear();
336  return n;
337  }
338  }
339  /* pp */ boolean removeDiscoveredDevice(final BTDevice device) {
340  return removeDiscoveredDeviceImpl2j( device.getAddressAndType() );
341  }
342 
343  @Override
344  public boolean removeDiscoveredDevice(final BDAddressAndType addressAndType) {
345  final boolean cj = removeDiscoveredDeviceImpl2j(addressAndType);
346  final boolean cn = removeDiscoveredDeviceImpl1(addressAndType.address.b, addressAndType.type.value);
347  if( DEBUG ) {
348  if( cj != cn ) {
349  System.err.println("DBTAdapter::removeDevices("+addressAndType+"): Unexpected discovered device count: Native "+cn+", callback "+cj);
350  }
351  }
352  return cn;
353  }
354  private native boolean removeDiscoveredDeviceImpl1(final byte[] address, final byte addressType);
355 
356  private boolean removeDiscoveredDeviceImpl2j(final BDAddressAndType addressAndType) {
357  synchronized(discoveredDevicesLock) {
358  for(final Iterator<WeakReference<BTDevice>> it = discoveredDevices.iterator(); it.hasNext();) {
359  final BTDevice d = it.next().get();
360  if( null == d ) {
361  it.remove();
362  } else if( d.getAddressAndType().equals(addressAndType) ) {
363  it.remove();
364  return true;
365  }
366  }
367  }
368  return false;
369  }
370  @Override
371  public List<BTDevice> getDiscoveredDevices() {
372  final ArrayList<BTDevice> res = new ArrayList<BTDevice>();
373  synchronized(discoveredDevicesLock) {
374  for(final Iterator<WeakReference<BTDevice>> it = discoveredDevices.iterator(); it.hasNext();) {
375  final BTDevice d = it.next().get();
376  if( null == d ) {
377  it.remove();
378  } else {
379  res.add(d);
380  }
381  }
382  }
383  return res;
384  }
385  private void cleanDiscoveredDevice() {
386  synchronized(discoveredDevicesLock) {
387  for(final Iterator<WeakReference<BTDevice>> it = discoveredDevices.iterator(); it.hasNext();) {
388  final BTDevice d = it.next().get();
389  if( null == d ) {
390  it.remove();
391  }
392  }
393  }
394  }
395 
396  @Override
397  public final boolean addStatusListener(final AdapterStatusListener l) {
398  final boolean added = addStatusListenerImpl(null, l);
399  if( PRINT_DEVICE_LISTS || DEBUG ) {
400  BTUtils.fprintf_td(System.err, "BTAdapter::addStatusListener: added %b, %s", added, toString());
402  }
403  return added;
404  }
405  /* pp */ native boolean addStatusListenerImpl(final BTDevice deviceOwnerAndMatch, final AdapterStatusListener l);
406 
407  @Override
408  public boolean removeStatusListener(final AdapterStatusListener l) {
409  boolean res = false;
410  if( !isClosing.get() ) {
411  res = removeStatusListenerImpl(l);
412  }
413  if( PRINT_DEVICE_LISTS || DEBUG ) {
414  BTUtils.fprintf_td(System.err, "BTAdapter::removeStatusListener: removed %b, %s", res, toString());
416  }
417  return false;
418  }
419  /* pp */ native boolean removeStatusListenerImpl(final AdapterStatusListener l);
420 
421  @Override
422  public native int removeAllStatusListener();
423 
424  @Override
425  public final void printDeviceLists() {
426  printDeviceListsImpl();
427  List<WeakReference<BTDevice>> _discoveredDevices;
428  synchronized(discoveredDevicesLock) {
429  // Shallow (but expensive) copy to avoid java.util.ConcurrentModificationException while iterating: debug mode only
430  _discoveredDevices = new ArrayList<WeakReference<BTDevice>>(discoveredDevices);
431  }
432  final int sz = _discoveredDevices.size();
433  BTUtils.fprintf_td(System.err, "- BTAdapter::DiscoveredDevicesJ: %d elements%s", sz, System.lineSeparator());
434  int idx = 0;
435  for(final Iterator<WeakReference<BTDevice>> it = _discoveredDevices.iterator(); it.hasNext(); ++idx) {
436  final BTDevice d = it.next().get();
437  if( null == d ) {
438  BTUtils.fprintf_td(System.err, " - %d / %d: nil%s", (idx+1), sz, System.lineSeparator());
439  } else {
440  BTUtils.fprintf_td(System.err, " - %d / %d: %s, name '%s'%s", (idx+1), sz,
441  d.getAddressAndType().toString(), d.getName(), System.lineSeparator());
442  }
443  }
444  }
445  private final native void printDeviceListsImpl();
446 
447  ////////////////////////////////////
448 
449  private final AdapterStatusListener statusListener = new AdapterStatusListener() {
450  @Override
451  public void adapterSettingsChanged(final BTAdapter a, final AdapterSettings oldmask, final AdapterSettings newmask,
452  final AdapterSettings changedmask, final long timestamp) {
453  final boolean initialSetting = oldmask.isEmpty();
454  if( DEBUG ) {
455  if( initialSetting ) {
456  System.err.println("Adapter.StatusListener.SETTINGS: "+oldmask+" -> "+newmask+", initial "+changedmask+" on "+a);
457  } else {
458  System.err.println("Adapter.StatusListener.SETTINGS: "+oldmask+" -> "+newmask+", changed "+changedmask+" on "+a);
459  }
460  }
461  if( initialSetting ) {
462  powered_state.set( newmask.isSet(AdapterSettings.SettingType.POWERED) );
463  isDiscoverable.set( newmask.isSet(AdapterSettings.SettingType.DISCOVERABLE) );
464  return;
465  }
466  if( changedmask.isSet(AdapterSettings.SettingType.POWERED) ) {
467  final boolean _isPowered = newmask.isSet(AdapterSettings.SettingType.POWERED);
468  if( powered_state.compareAndSet(!_isPowered, _isPowered) ) {
469  if( !_isPowered ) {
470  poweredOff();
471  }
472  }
473  }
474  if( changedmask.isSet(AdapterSettings.SettingType.DISCOVERABLE) ) {
475  final boolean _isDiscoverable = newmask.isSet(AdapterSettings.SettingType.DISCOVERABLE);
476  if( isDiscoverable.compareAndSet(!_isDiscoverable, _isDiscoverable) ) {
477  }
478  }
479  }
480  @Override
481  public void discoveringChanged(final BTAdapter adapter, final ScanType currentMeta, final ScanType changedType, final boolean changedEnabled, final boolean keepAlive, final long timestamp) {
482  if( DEBUG ) {
483  System.err.println("Adapter.StatusListener.DISCOVERING: meta "+currentMeta+", changed["+changedType+", enabled "+changedEnabled+", keepAlive "+keepAlive+"] on "+adapter);
484  }
485  // meta ignores changes on temp disabled discovery
486  currentMetaScanType.set(currentMeta);
487  }
488  @Override
489  public boolean deviceFound(final BTDevice device, final long timestamp) {
490  synchronized(discoveredDevicesLock) {
491  cleanDiscoveredDevice();
492  discoveredDevices.add(new WeakReference<BTDevice>(device));
493  }
494  if( PRINT_DEVICE_LISTS || DEBUG ) {
495  System.err.println("Adapter.FOUND: discoveredDevices "+ discoveredDevices.size() + ": "+device+", on "+device.getAdapter());
496  }
497  return false;
498  }
499 
500  @Override
501  public void deviceUpdated(final BTDevice device, final EIRDataTypeSet updateMask, final long timestamp) {
502  final boolean rssiUpdated = updateMask.isSet( EIRDataTypeSet.DataType.RSSI );
503  final boolean mdUpdated = updateMask.isSet( EIRDataTypeSet.DataType.MANUF_DATA );
504  if( DEBUG && !rssiUpdated && !mdUpdated) {
505  System.err.println("Adapter.UPDATED: "+updateMask+" of "+device+" on "+device.getAdapter());
506  }
507  // nop on discoveredDevices
508  }
509 
510  @Override
511  public void deviceConnected(final BTDevice device, final short handle, final long timestamp) {
512  if( DEBUG ) {
513  System.err.println("Adapter.CONNECTED: "+device+" on "+device.getAdapter());
514  }
515  }
516 
517  @Override
518  public void devicePairingState(final BTDevice device, final SMPPairingState state, final PairingMode mode, final long timestamp) {
519  if( DEBUG ) {
520  System.err.println("Adapter.PAIRING_STATE: state "+state+", mode "+mode+": "+device);
521  }
522  }
523 
524  @Override
525  public void deviceReady(final BTDevice device, final long timestamp) {
526  if( DEBUG ) {
527  System.err.println("Adapter.READY: "+device);
528  }
529  }
530 
531  @Override
532  public void deviceDisconnected(final BTDevice device, final HCIStatusCode reason, final short handle, final long timestamp) {
533  if( DEBUG ) {
534  System.err.println("Adapter.DISCONNECTED: Reason "+reason+", old handle 0x"+Integer.toHexString(handle)+": "+device+" on "+device.getAdapter());
535  }
536  }
537 
538  @Override
539  public String toString() {
540  return "AdapterStatusListener[adapter "+addressAndType.toString()+"]";
541  }
542 
543  };
544 
545  /**
546  * Returns the matching {@link DBTObject} from the internal cache if found,
547  * otherwise {@code null}.
548  * <p>
549  * The returned {@link DBTObject} may be of type
550  * <ul>
551  * <li>{@link DBTDevice}</li>
552  * <li>{@link DBTGattService}</li>
553  * <li>{@link DBTGattChar}</li>
554  * <li>{@link DBTGattDesc}</li>
555  * </ul>
556  * or alternatively in {@link BTObject} space
557  * <ul>
558  * <li>{@link BTType#DEVICE} -> {@link BTDevice}</li>
559  * <li>{@link BTType#GATT_SERVICE} -> {@link BTGattService}</li>
560  * <li>{@link BTType#GATT_CHARACTERISTIC} -> {@link BTGattChar}</li>
561  * <li>{@link BTType#GATT_DESCRIPTOR} -> {@link BTGattDesc}</li>
562  * </ul>
563  * </p>
564  * @param name name of the desired {@link BTType#DEVICE device}.
565  * Maybe {@code null}.
566  * @param identifier EUI48 address of the desired {@link BTType#DEVICE device}
567  * or UUID of the desired {@link BTType#GATT_SERVICE service},
568  * {@link BTType#GATT_CHARACTERISTIC characteristic} or {@link BTType#GATT_DESCRIPTOR descriptor} to be found.
569  * Maybe {@code null}, in which case the first object of the desired type is being returned - if existing.
570  * @param type specify the type of the object to be found, either
571  * {@link BTType#DEVICE device},
572  * {@link BTType#GATT_SERVICE service}, {@link BTType#GATT_CHARACTERISTIC characteristic}
573  * or {@link BTType#GATT_DESCRIPTOR descriptor}.
574  * {@link BTType#NONE none} means anything.
575  */
576  /* pp */ DBTObject findInCache(final String name, final String identifier, final BTType type) {
577  final boolean anyType = BTType.NONE == type;
578  final boolean deviceType = BTType.DEVICE == type;
579  final boolean serviceType = BTType.GATT_SERVICE == type;
580  final boolean charType = BTType.GATT_CHARACTERISTIC== type;
581  final boolean descType = BTType.GATT_DESCRIPTOR == type;
582 
583  if( !anyType && !deviceType && !serviceType && !charType && !descType ) {
584  return null;
585  }
586  synchronized(discoveredDevicesLock) {
587  cleanDiscoveredDevice();
588 
589  if( null == name && null == identifier && ( anyType || deviceType ) ) {
590  // special case for 1st valid device
591  if( discoveredDevices.size() > 0 ) {
592  return (DBTDevice) discoveredDevices.get(0).get();
593  }
594  return null; // no device
595  }
596  for(int devIdx = discoveredDevices.size() - 1; devIdx >= 0; devIdx-- ) {
597  final DBTDevice device = (DBTDevice) discoveredDevices.get(devIdx).get();
598  if( ( anyType || deviceType ) ) {
599  if( null != name && null != identifier &&
600  device.getName().equals(name) &&
601  device.getAddressAndType().address.toString().equals(identifier)
602  )
603  {
604  return device;
605  }
606  if( null != identifier &&
607  device.getAddressAndType().address.toString().equals(identifier)
608  )
609  {
610  return device;
611  }
612  if( null != name &&
613  device.getName().equals(name)
614  )
615  {
616  return device;
617  }
618  }
619  if( anyType || serviceType || charType || descType ) {
620  final DBTObject dbtObj = device.findInCache(identifier, type);
621  if( null != dbtObj ) {
622  return dbtObj;
623  }
624  }
625  }
626  return null;
627  }
628  }
629 
630  /* pp */ DBTDevice findDeviceInCache(final String name, final BDAddressAndType addressAndType) {
631  synchronized(discoveredDevicesLock) {
632  cleanDiscoveredDevice();
633 
634  if( null == name && null == addressAndType ) {
635  // special case for 1st valid device
636  if( discoveredDevices.size() > 0 ) {
637  return (DBTDevice) discoveredDevices.get(0).get();
638  }
639  return null; // no device
640  }
641  for(int devIdx = discoveredDevices.size() - 1; devIdx >= 0; devIdx-- ) {
642  final DBTDevice device = (DBTDevice) discoveredDevices.get(devIdx).get();
643  if( null != name && null != addressAndType &&
644  device.getName().equals(name) &&
645  device.getAddressAndType().equals(addressAndType)
646  )
647  {
648  return device;
649  }
650  if( null != addressAndType &&
651  device.getAddressAndType().equals(addressAndType)
652  )
653  {
654  return device;
655  }
656  if( null != name &&
657  device.getName().equals(name)
658  )
659  {
660  return device;
661  }
662  }
663  return null;
664  }
665  }
666 }
org.direct_bt.BDAddressAndType.equals
final boolean equals(final Object obj)
Definition: BDAddressAndType.java:107
jau.direct_bt.DBTObject.DBTObject
DBTObject(final long nativeInstance, final int hashValue)
Definition: DBTObject.java:46
org.direct_bt.BDAddressType.value
final byte value
Definition: BDAddressType.java:63
jau.direct_bt.DBTAdapter.getVisibleAddressAndType
BDAddressAndType getVisibleAddressAndType()
Returns the adapter's currently visible BDAddressAndType.
Definition: DBTAdapter.java:156
org.direct_bt.ScanType.get
static ScanType get(final byte value)
Maps the specified integer value to a constant of ScanType.
Definition: ScanType.java:60
org.direct_bt.BTAdapter
Provides access to Bluetooth adapters.
Definition: BTAdapter.java:41
org.direct_bt.AdapterSettings.isSet
boolean isSet(final SettingType bit)
Definition: AdapterSettings.java:184
jau.direct_bt.DBTAdapter.removeDiscoveredDevice
boolean removeDiscoveredDevice(final BDAddressAndType addressAndType)
Discards matching discovered devices.
Definition: DBTAdapter.java:344
org.direct_bt.BTUtils.fprintf_td
static void fprintf_td(final PrintStream out, final String format, final Object ... args)
Convenient PrintStream#printf(String, Object...) invocation, prepending the elapsedTimeMillis() times...
Definition: BTUtils.java:68
org.direct_bt.AdapterSettings.isEmpty
boolean isEmpty()
Definition: AdapterSettings.java:183
jau.direct_bt.DBTAdapter.getManager
final BTManager getManager()
Returns the used singleton BTManager instance, used to create this adapter.
Definition: DBTAdapter.java:103
jau.direct_bt.DBTAdapter.setDiscoverable
native boolean setDiscoverable(boolean value)
Sets the discoverable state the adapter.
jau.direct_bt.DBTAdapter.removeStatusListener
boolean removeStatusListener(final AdapterStatusListener l)
Remove the given AdapterStatusListener from the list.
Definition: DBTAdapter.java:408
org.direct_bt
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2020 Gothel Software e.K.
org.direct_bt.PairingMode
Bluetooth secure pairing mode.
Definition: PairingMode.java:40
jau.direct_bt.DBTAdapter.getBluetoothType
BTType getBluetoothType()
Returns the BluetoothType of this object.
Definition: DBTAdapter.java:165
jau.direct_bt.DBTAdapter.removeDeviceFromWhitelist
boolean removeDeviceFromWhitelist(final BDAddressAndType addressAndType)
Remove the given device from the adapter's autoconnect whitelist.
Definition: DBTAdapter.java:203
jau.direct_bt.DBTAdapter.startDiscovery
HCIStatusCode startDiscovery(final boolean keepAlive, final boolean le_scan_active, final short le_scan_interval, final short le_scan_window, final byte filter_policy)
Shares same implementation as startDiscovery(boolean, boolean), but allows setting custom scan values...
Definition: DBTAdapter.java:284
jau.direct_bt.DBTAdapter.isValid
final boolean isValid()
Returns whether the adapter is valid, i.e.
Definition: DBTAdapter.java:271
org.direct_bt.EUI48
A packed 48 bit EUI-48 identifier, formerly known as MAC-48 or simply network device MAC address (Med...
Definition: EUI48.java:37
jau.direct_bt.DBTAdapter.find
BTDevice find(final String name, final BDAddressAndType addressAndType)
Find a BluetoothDevice.
Definition: DBTAdapter.java:175
jau.direct_bt.DBTManager
Definition: DBTManager.java:51
jau.direct_bt.DBTAdapter.startDiscovery
HCIStatusCode startDiscovery(final boolean keepAlive, final boolean le_scan_active)
Turns on device discovery if it is disabled.
Definition: DBTAdapter.java:280
org.direct_bt.HCIWhitelistConnectType
HCI Whitelist connection type.
Definition: HCIWhitelistConnectType.java:32
org.direct_bt.BDAddressAndType.toString
final String toString()
Definition: BDAddressAndType.java:154
jau.direct_bt.DBTAdapter.reset
final HCIStatusCode reset()
Reset the adapter.
Definition: DBTAdapter.java:236
jau.direct_bt.DBTAdapter.setPairable
native boolean setPairable(boolean value)
Sets the discoverable state the adapter.
jau.direct_bt.DBTAdapter.getName
String getName()
Returns the system name of this adapter.
Definition: DBTAdapter.java:159
org.direct_bt.BTGattService
Provides access to Bluetooth GATT characteristic.
Definition: BTGattService.java:41
jau.direct_bt.DBTAdapter.getAlias
native String getAlias()
Returns the friendly name of this adapter.
jau.direct_bt.DBTAdapter.getCurrentScanType
final ScanType getCurrentScanType()
Returns the current meta discovering ScanType.
Definition: DBTAdapter.java:214
jau.direct_bt.DBTAdapter.find
BTDevice find(final String name, final BDAddressAndType addressAndType, final long timeoutMS)
Find a BluetoothDevice.
Definition: DBTAdapter.java:170
org.direct_bt.BTManager
Definition: BTManager.java:34
org.direct_bt.EIRDataTypeSet
Bit mask of 'Extended Inquiry Response' (EIR) data fields, indicating a set of related data.
Definition: EIRDataTypeSet.java:33
org.direct_bt.BDAddressAndType.type
BDAddressType type
Definition: BDAddressAndType.java:47
jau.direct_bt.DBTAdapter.isSuspended
final boolean isSuspended()
Returns whether the adapter is suspended, i.e.
Definition: DBTAdapter.java:267
jau.direct_bt.DBTDevice
Definition: DBTDevice.java:58
org.direct_bt.AdapterSettings
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2020 Gothel Software e.K.
Definition: AdapterSettings.java:146
jau.direct_bt.DBTAdapter.toString
String toString()
Definition: DBTAdapter.java:219
jau.direct_bt.DBTAdapter
Definition: DBTAdapter.java:59
org.direct_bt.HCIStatusCode.get
static HCIStatusCode get(final String name)
Maps the specified name to a constant of HCIStatusCode.
Definition: HCIStatusCode.java:143
org.direct_bt.SMPPairingState
SMP Pairing Process state definition.
Definition: SMPPairingState.java:38
jau.direct_bt.DBTAdapter.stopDiscovery
HCIStatusCode stopDiscovery()
Turns off device discovery if it is enabled.
Definition: DBTAdapter.java:304
jau.direct_bt.DBTAdapter.equals
boolean equals(final Object obj)
Definition: DBTAdapter.java:140
org.direct_bt.BDAddressAndType
Unique Bluetooth EUI48 address and BDAddressType tuple.
Definition: BDAddressAndType.java:36
jau.direct_bt.DBTAdapter.removeDiscoveredDevices
int removeDiscoveredDevices()
Remove all the discovered devices found on this adapter.
Definition: DBTAdapter.java:321
jau.direct_bt.DBTAdapter.getDevID
int getDevID()
Returns the BluetoothAdapter's internal temporary device id.
Definition: DBTAdapter.java:162
jau.direct_bt.DBTAdapter.getDiscoverable
boolean getDiscoverable()
Returns the discoverable state the adapter.
Definition: DBTAdapter.java:211
org.direct_bt.ScanType
Meta ScanType as derived from BTMode with defined value mask consisting of BDAddressType bits.
Definition: ScanType.java:36
jau.direct_bt.DBTAdapter.deleteImpl
native void deleteImpl(long nativeInstance)
Deletes the native instance.
jau.direct_bt.DBTAdapter.addDeviceToWhitelist
boolean addDeviceToWhitelist(final BDAddressAndType addressAndType, final HCIWhitelistConnectType ctype)
Add the given device to the adapter's autoconnect whitelist.
Definition: DBTAdapter.java:196
jau.direct_bt.DBTManager.getManager
static BTManager getManager()
Returns an instance of BluetoothManager, to be used instead of constructor.
Definition: DBTManager.java:398
org.direct_bt.BTUtils
Definition: BTUtils.java:29
org.direct_bt.EUI48.b
final byte b[]
The 6 byte EUI48 address.
Definition: EUI48.java:52
org.direct_bt.ScanType.NONE
NONE
Definition: ScanType.java:37
jau.direct_bt.DBTAdapter.isDeviceWhitelisted
final boolean isDeviceWhitelisted(final BDAddressAndType addressAndType)
Returns true, if the adapter's device is already whitelisted.
Definition: DBTAdapter.java:180
org.direct_bt.HCIStatusCode
BT Core Spec v5.2: Vol 1, Part F Controller Error Codes: 1.3 List of Error Codes.
Definition: HCIStatusCode.java:34
jau.direct_bt.DBTDevice.close
void close()
Release the native memory associated with this object The object should not be used following a call ...
Definition: DBTDevice.java:121
jau.direct_bt.DBTAdapter.getAddressAndType
BDAddressAndType getAddressAndType()
Returns the adapter's public BDAddressAndType.
Definition: DBTAdapter.java:153
org.direct_bt.BTGattChar
Provides access to Bluetooth GATT characteristic.
Definition: BTGattChar.java:40
jau.direct_bt.DBTAdapter.getPoweredState
boolean getPoweredState()
Returns the power state the adapter.
Definition: DBTAdapter.java:260
org.direct_bt.BTDevice
Provides access to Bluetooth adapters.
Definition: BTDevice.java:42
jau.direct_bt.DBTAdapter.setAlias
native void setAlias(final String value)
Sets the friendly name of this adapter.
org.direct_bt.BTGattDesc
Provides access to Bluetooth GATT descriptor.
Definition: BTGattDesc.java:38
jau.direct_bt.DBTManager.DEBUG
static final boolean DEBUG
Definition: DBTManager.java:52
org
org.direct_bt.BTType
Definition: BTType.java:28
org.direct_bt.BTException
Definition: BTException.java:32
org.direct_bt.BTDevice.getAddressAndType
BDAddressAndType getAddressAndType()
Returns the unique device EUI48 address and BDAddressType type.
jau.direct_bt.DBTAdapter.connectDevice
final BTDevice connectDevice(final BDAddressAndType addressAndType)
This method connects to device without need of performing General Discovery.
Definition: DBTAdapter.java:251
jau.direct_bt.DBTAdapter.setPowered
native boolean setPowered(boolean value)
Sets the power state the adapter.
org.direct_bt.BDAddressType
Bluetooth address type constants.
Definition: BDAddressType.java:53
org.direct_bt.BTType.ADAPTER
ADAPTER
Definition: BTType.java:29
jau.direct_bt.DBTAdapter.printDeviceLists
final void printDeviceLists()
Print the internally maintained BTDevice lists to stderr:
Definition: DBTAdapter.java:425
jau.direct_bt.DBTAdapter.isPowered
final boolean isPowered()
Returns whether the adapter is valid, plugged in and powered.
Definition: DBTAdapter.java:263
jau.direct_bt.DBTAdapter.getDiscoveredDevices
List< BTDevice > getDiscoveredDevices()
Returns a list of discovered BluetoothDevices from this adapter.
Definition: DBTAdapter.java:371
org.direct_bt.BTObject
Definition: BTObject.java:31
jau.direct_bt.DBTAdapter.addDeviceToWhitelist
boolean addDeviceToWhitelist(final BDAddressAndType addressAndType, final HCIWhitelistConnectType ctype, final short conn_interval_min, final short conn_interval_max, final short conn_latency, final short timeout)
Add the given device to the adapter's autoconnect whitelist.
Definition: DBTAdapter.java:184
jau.direct_bt.DBTAdapter.isSuspendedImpl
native boolean isSuspendedImpl()
jau.direct_bt.DBTAdapter.isValidImpl
native boolean isValidImpl()
org.direct_bt.BTDevice.getName
String getName()
Returns the remote friendly name of this device.
jau.direct_bt.DBTAdapter.isPoweredImpl
native boolean isPoweredImpl()
org.direct_bt.AdapterStatusListener
BTAdapter status listener for BTDevice discovery events: Added, updated and removed; as well as for c...
Definition: AdapterStatusListener.java:56
org.direct_bt.BDAddressType.get
static BDAddressType get(final String name)
Maps the specified name to a constant of BDAddressType.
Definition: BDAddressType.java:104
org.direct_bt.BDAddressAndType.address
EUI48 address
Definition: BDAddressAndType.java:46
org.direct_bt.BTDevice.remove
boolean remove()
Remove this device from the system (like an unpair).
jau.direct_bt.DBTAdapter.addStatusListener
final boolean addStatusListener(final AdapterStatusListener l)
Add the given AdapterStatusListener to the list if not already present.
Definition: DBTAdapter.java:397
jau.direct_bt.DBTAdapter.close
void close()
Release the native memory associated with this object The object should not be used following a call ...
Definition: DBTAdapter.java:106
org.direct_bt.HCIWhitelistConnectType.value
final int value
Definition: HCIWhitelistConnectType.java:40
jau.direct_bt.DBTAdapter.removeAllStatusListener
native int removeAllStatusListener()
Remove all AdapterStatusListener from the list.
jau.direct_bt.DBTObject
Definition: DBTObject.java:32