bluetooth tweaks

Add a single method to provide candidate devices; don't bother passing
bogus BT MAC addrs; let instance belonging to background-user start
communicating again when user becomes foreground.
This commit is contained in:
Eric House 2020-10-07 19:39:51 -07:00
parent 284e7eb85a
commit 8240f753ca
5 changed files with 88 additions and 67 deletions

View file

@ -262,7 +262,8 @@ public class BTInviteDelegate extends InviteDelegate {
sPersistedRef[0].add( "00:00:00:00:00:00", "Do Not Invite Me" ); sPersistedRef[0].add( "00:00:00:00:00:00", "Do Not Invite Me" );
} }
int count = BTService.getPairedCount( m_activity ); Set<BluetoothDevice> devs = BTService.getCandidates();
int count = devs.size();
if ( 0 < count ) { if ( 0 < count ) {
mNDevsThisScan = 0; mNDevsThisScan = 0;
showProgress( count, 2 * SCAN_SECONDS ); showProgress( count, 2 * SCAN_SECONDS );
@ -330,7 +331,7 @@ public class BTInviteDelegate extends InviteDelegate {
Log.d( TAG, "removeNotPaired()" ); Log.d( TAG, "removeNotPaired()" );
BluetoothAdapter adapter = BTService.getAdapterIf(); BluetoothAdapter adapter = BTService.getAdapterIf();
if ( null != adapter ) { if ( null != adapter ) {
Set<BluetoothDevice> pairedDevs = adapter.getBondedDevices(); Set<BluetoothDevice> pairedDevs = BTService.getCandidates();
Set<String> paired = new HashSet<>(); Set<String> paired = new HashSet<>();
for ( BluetoothDevice dev : pairedDevs ) { for ( BluetoothDevice dev : pairedDevs ) {
Log.d( TAG, "removeNotPaired(): paired dev: %s", dev.getName() ); Log.d( TAG, "removeNotPaired(): paired dev: %s", dev.getName() );

View file

@ -50,10 +50,12 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
// Notes on running under Oreo // Notes on running under Oreo
// //
@ -84,6 +86,7 @@ public class BTService extends XWJIService {
XWJIService.register( BTService.class, sJobID, XWJIService.register( BTService.class, sJobID,
CommsConnType.COMMS_CONN_BT ); CommsConnType.COMMS_CONN_BT );
} }
private static AtomicBoolean sBackUser = new AtomicBoolean(false);
// half minute for testing; maybe 15 on ship? Or make it a debug config. // half minute for testing; maybe 15 on ship? Or make it a debug config.
private static int DEFAULT_KEEPALIVE_SECONDS = 15 * 60; private static int DEFAULT_KEEPALIVE_SECONDS = 15 * 60;
@ -166,10 +169,19 @@ public class BTService extends XWJIService {
public static BluetoothAdapter getAdapterIf() public static BluetoothAdapter getAdapterIf()
{ {
BluetoothAdapter result = null;
// Later this will change to include at least a test whether we're // Later this will change to include at least a test whether we're
// running as background user account, a situation in which BT crashes // running as background user account, a situation in which BT crashes
// a lot inside the OS. // a lot inside the OS.
return BluetoothAdapter.getDefaultAdapter(); if ( !sBackUser.get() ) {
result = BluetoothAdapter.getDefaultAdapter();
}
return result;
}
public static void setAmForeground()
{
sBackUser.set(false);
} }
public static boolean BTAvailable() public static boolean BTAvailable()
@ -184,6 +196,13 @@ public class BTService extends XWJIService {
return null != adapter && adapter.isEnabled(); return null != adapter && adapter.isEnabled();
} }
public static boolean isBogusAddr( String addr )
{
boolean result = BOGUS_MARSHMALLOW_ADDR.equals( addr );
Log.d( TAG, "isBogusAddr(%s) => %b", addr, result );
return result;
}
public static void enable() public static void enable()
{ {
BluetoothAdapter adapter = getAdapterIf(); BluetoothAdapter adapter = getAdapterIf();
@ -195,18 +214,14 @@ public class BTService extends XWJIService {
public static String[] getBTNameAndAddress() public static String[] getBTNameAndAddress()
{ {
BluetoothAdapter adapter = getAdapterIf(); String[] result = null;
return null == adapter ? null
: new String[] { adapter.getName(), adapter.getAddress() };
}
public static int getPairedCount( Activity activity )
{
int result = 0;
BluetoothAdapter adapter = getAdapterIf(); BluetoothAdapter adapter = getAdapterIf();
if ( null != adapter ) { if ( null != adapter ) {
Set<BluetoothDevice> pairedDevs = adapter.getBondedDevices(); String addr = adapter.getAddress();
result = pairedDevs.size(); if ( isBogusAddr( addr ) ) {
addr = null;
}
result = new String[] { adapter.getName(), addr };
} }
return result; return result;
} }
@ -357,8 +372,7 @@ public class BTService extends XWJIService {
BluetoothAdapter adapter = getAdapterIf(); BluetoothAdapter adapter = getAdapterIf();
if ( null != adapter && adapter.isEnabled() ) { if ( null != adapter && adapter.isEnabled() ) {
m_adapter = adapter; m_adapter = adapter;
Log.i( TAG, "onCreate(); bt name = %s; bt addr = %s", Log.i( TAG, "onCreate(); my BT name: %s", adapter.getName() );
adapter.getName(), adapter.getAddress() );
startListener(); startListener();
} else { } else {
Log.w( TAG, "not starting threads: BT not available" ); Log.w( TAG, "not starting threads: BT not available" );
@ -565,6 +579,7 @@ public class BTService extends XWJIService {
// listenUsingRfcommWithServiceRecord() in background (on // listenUsingRfcommWithServiceRecord() in background (on
// Android 9) // Android 9)
m_serverSocket = null; m_serverSocket = null;
sBackUser.set( true );
// I'm seeing too much of this on two-user systems. // I'm seeing too much of this on two-user systems.
// Log.ex( TAG, ex ); // Log.ex( TAG, ex );
} }
@ -681,7 +696,7 @@ public class BTService extends XWJIService {
private static String getSafeAddr( CommsAddrRec addr ) private static String getSafeAddr( CommsAddrRec addr )
{ {
String btAddr = addr.bt_btAddr; String btAddr = addr.bt_btAddr;
if ( BOGUS_MARSHMALLOW_ADDR.equals( btAddr ) ) { if ( TextUtils.isEmpty(btAddr) || BOGUS_MARSHMALLOW_ADDR.equals( btAddr ) ) {
String btName = addr.bt_hostName; String btName = addr.bt_hostName;
if ( null == s_namesToAddrs ) { if ( null == s_namesToAddrs ) {
s_namesToAddrs = new HashMap<>(); s_namesToAddrs = new HashMap<>();
@ -692,16 +707,14 @@ public class BTService extends XWJIService {
} else { } else {
btAddr = null; btAddr = null;
} }
if ( null == btAddr ) { if ( TextUtils.isEmpty( btAddr ) ) {
BluetoothAdapter adapter = getAdapterIf(); Set<BluetoothDevice> devs = getCandidates();
if ( null != adapter ) { for ( BluetoothDevice dev : devs ) {
for ( BluetoothDevice dev : adapter.getBondedDevices() ) { // Log.d( TAG, "%s => %s", dev.getName(), dev.getAddress() );
// Log.d( TAG, "%s => %s", dev.getName(), dev.getAddress() ); if ( btName.equals( dev.getName() ) ) {
if ( btName.equals( dev.getName() ) ) { btAddr = dev.getAddress();
btAddr = dev.getAddress(); s_namesToAddrs.put( btName, btAddr );
s_namesToAddrs.put( btName, btAddr ); break;
break;
}
} }
} }
} }
@ -709,33 +722,34 @@ public class BTService extends XWJIService {
return btAddr; return btAddr;
} }
public static Set<BluetoothDevice> getCandidates()
{
Set<BluetoothDevice> result = new HashSet<>();
BluetoothAdapter adapter = getAdapterIf();
if ( null != adapter ) {
for ( BluetoothDevice dev : adapter.getBondedDevices() ) {
int clazz = dev.getBluetoothClass().getMajorDeviceClass();
switch ( clazz ) {
case Major.AUDIO_VIDEO:
case Major.HEALTH:
case Major.IMAGING:
case Major.TOY:
case Major.PERIPHERAL:
break;
default:
result.add( dev );
break;
}
}
}
return result;
}
private void sendPings( MultiEvent event, int timeoutMS ) private void sendPings( MultiEvent event, int timeoutMS )
{ {
Set<BluetoothDevice> pairedDevs = m_adapter.getBondedDevices(); Set<BluetoothDevice> pairedDevs = getCandidates();
Map<BluetoothDevice, PacketAccumulator> pas = new HashMap<>(); Map<BluetoothDevice, PacketAccumulator> pas = new HashMap<>();
for ( BluetoothDevice dev : pairedDevs ) { for ( BluetoothDevice dev : pairedDevs ) {
// Skip things that can't host an Android app. BUT: one of my
// phones, and presumably lots of others, aren't listed as
// PHONE. So let's try negative testing instead
int clazz = dev.getBluetoothClass().getMajorDeviceClass();
String reject = null;
switch ( clazz ) {
case Major.AUDIO_VIDEO:
reject = "audio"; break;
case Major.HEALTH:
reject = "health"; break;
case Major.IMAGING:
reject = "imaging"; break;
case Major.TOY:
reject = "toy"; break;
case Major.PERIPHERAL:
reject = "peripheral"; break;
}
if ( null != reject ) {
Log.d( TAG, "sendPings(): %s is a %s; dropping", dev.getName(), reject );
continue;
}
Log.d( TAG, "sendPings(): sending to %s (a %d)", dev.getName(), clazz );
PacketAccumulator pa = PacketAccumulator pa =
new PacketAccumulator( dev.getAddress(), timeoutMS ) new PacketAccumulator( dev.getAddress(), timeoutMS )
.addPing( 0 ) .addPing( 0 )
@ -1437,18 +1451,15 @@ public class BTService extends XWJIService {
{ {
Assert.assertFalse( BOGUS_MARSHMALLOW_ADDR.equals( addr ) ); Assert.assertFalse( BOGUS_MARSHMALLOW_ADDR.equals( addr ) );
String result = "<unknown>"; String result = "<unknown>";
BluetoothAdapter adapter = getAdapterIf(); Set<BluetoothDevice> devs = getCandidates();
if ( null != adapter ) { Iterator<BluetoothDevice> iter = devs.iterator();
Set<BluetoothDevice> devs = adapter.getBondedDevices(); while ( iter.hasNext() ) {
Iterator<BluetoothDevice> iter = devs.iterator(); BluetoothDevice dev = iter.next();
while ( iter.hasNext() ) { String devAddr = dev.getAddress();
BluetoothDevice dev = iter.next(); Assert.assertFalse( BOGUS_MARSHMALLOW_ADDR.equals( devAddr ) );
String devAddr = dev.getAddress(); if ( devAddr.equals( addr ) ) {
Assert.assertFalse( BOGUS_MARSHMALLOW_ADDR.equals( devAddr ) ); result = dev.getName();
if ( devAddr.equals( addr ) ) { break;
result = dev.getName();
break;
}
} }
} }
return result; return result;
@ -1562,10 +1573,12 @@ public class BTService extends XWJIService {
private static PacketAccumulator getSenderFor( String addr, boolean create ) private static PacketAccumulator getSenderFor( String addr, boolean create )
{ {
Assert.assertTrueNR( ! BOGUS_MARSHMALLOW_ADDR.equals( addr ) );
PacketAccumulator result; PacketAccumulator result;
try ( DeadlockWatch dw = new DeadlockWatch( sSenders ) ) { try ( DeadlockWatch dw = new DeadlockWatch( sSenders ) ) {
synchronized ( sSenders ) { synchronized ( sSenders ) {
if ( create && !sSenders.containsKey( addr ) ) { if ( create && !sSenders.containsKey( addr ) ) {
// Log.d( TAG, "adding %s to senders", addr );
sSenders.put( addr, new PacketAccumulator( addr ) ); sSenders.put( addr, new PacketAccumulator( addr ) );
} }
result = sSenders.get( addr ); result = sSenders.get( addr );

View file

@ -149,6 +149,7 @@ public abstract class DelegateBase implements DlgClickNotify,
m_isVisible = true; m_isVisible = true;
XWServiceHelper.setListener( this ); XWServiceHelper.setListener( this );
runIfVisible(); runIfVisible();
BTService.setAmForeground();
} }
protected void onPause() protected void onPause()

View file

@ -450,8 +450,10 @@ public class NetLaunchInfo implements Serializable {
} }
if ( addrs.contains( CommsConnType.COMMS_CONN_BT ) ) { if ( addrs.contains( CommsConnType.COMMS_CONN_BT ) ) {
obj.put( MultiService.BT_NAME, btName ) obj.put( MultiService.BT_NAME, btName );
.put( MultiService.BT_ADDRESS, btAddress ); if ( ! BTService.isBogusAddr( btAddress ) ) {
obj.put( MultiService.BT_ADDRESS, btAddress );
}
} }
if ( addrs.contains( CommsConnType.COMMS_CONN_SMS ) ) { if ( addrs.contains( CommsConnType.COMMS_CONN_SMS ) ) {
obj.put( PHONE_KEY, phone ) obj.put( PHONE_KEY, phone )
@ -539,7 +541,7 @@ public class NetLaunchInfo implements Serializable {
case COMMS_CONN_BT: case COMMS_CONN_BT:
btAddress = json.optString( MultiService.BT_ADDRESS ); btAddress = json.optString( MultiService.BT_ADDRESS );
btName = json.optString( MultiService.BT_NAME ); btName = json.optString( MultiService.BT_NAME );
doAdd = !hasAddrs && !btAddress.isEmpty(); doAdd = !hasAddrs && !btName.isEmpty();
break; break;
case COMMS_CONN_RELAY: case COMMS_CONN_RELAY:
room = json.getString( MultiService.ROOM ); room = json.getString( MultiService.ROOM );
@ -612,7 +614,9 @@ public class NetLaunchInfo implements Serializable {
ub.appendQueryParameter( ID_KEY, inviteID ); ub.appendQueryParameter( ID_KEY, inviteID );
} }
if ( addrs.contains( CommsConnType.COMMS_CONN_BT ) ) { if ( addrs.contains( CommsConnType.COMMS_CONN_BT ) ) {
ub.appendQueryParameter( BTADDR_KEY, btAddress ); if ( null != btAddress ) {
ub.appendQueryParameter( BTADDR_KEY, btAddress );
}
ub.appendQueryParameter( BTNAME_KEY, btName ); ub.appendQueryParameter( BTNAME_KEY, btName );
} }
if ( addrs.contains( CommsConnType.COMMS_CONN_SMS ) ) { if ( addrs.contains( CommsConnType.COMMS_CONN_SMS ) ) {
@ -769,7 +773,7 @@ public class NetLaunchInfo implements Serializable {
valid = null != room && null != inviteID(); valid = null != room && null != inviteID();
break; break;
case COMMS_CONN_BT: case COMMS_CONN_BT:
valid = null != btAddress; valid = null != btName;
break; break;
case COMMS_CONN_SMS: case COMMS_CONN_SMS:
valid = null != phone && 0 < osVers; valid = null != phone && 0 < osVers;

View file

@ -338,7 +338,9 @@ public class CommsAddrRec implements java.io.Serializable {
public void setBTParams( String btAddr, String btName ) public void setBTParams( String btAddr, String btName )
{ {
bt_hostName = btName; bt_hostName = btName;
bt_btAddr = btAddr; if ( ! BTService.isBogusAddr( btAddr ) ) {
bt_btAddr = btAddr;
}
} }
public void setSMSParams( String phone ) public void setSMSParams( String phone )