From 8240f753ca71b8829d4677911001a07154c998ef Mon Sep 17 00:00:00 2001 From: Eric House Date: Wed, 7 Oct 2020 19:39:51 -0700 Subject: [PATCH] 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. --- .../eehouse/android/xw4/BTInviteDelegate.java | 5 +- .../org/eehouse/android/xw4/BTService.java | 131 ++++++++++-------- .../org/eehouse/android/xw4/DelegateBase.java | 1 + .../eehouse/android/xw4/NetLaunchInfo.java | 14 +- .../eehouse/android/xw4/jni/CommsAddrRec.java | 4 +- 5 files changed, 88 insertions(+), 67 deletions(-) diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTInviteDelegate.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTInviteDelegate.java index f8d3c187b..d2fe94dc6 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTInviteDelegate.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTInviteDelegate.java @@ -262,7 +262,8 @@ public class BTInviteDelegate extends InviteDelegate { sPersistedRef[0].add( "00:00:00:00:00:00", "Do Not Invite Me" ); } - int count = BTService.getPairedCount( m_activity ); + Set devs = BTService.getCandidates(); + int count = devs.size(); if ( 0 < count ) { mNDevsThisScan = 0; showProgress( count, 2 * SCAN_SECONDS ); @@ -330,7 +331,7 @@ public class BTInviteDelegate extends InviteDelegate { Log.d( TAG, "removeNotPaired()" ); BluetoothAdapter adapter = BTService.getAdapterIf(); if ( null != adapter ) { - Set pairedDevs = adapter.getBondedDevices(); + Set pairedDevs = BTService.getCandidates(); Set paired = new HashSet<>(); for ( BluetoothDevice dev : pairedDevs ) { Log.d( TAG, "removeNotPaired(): paired dev: %s", dev.getName() ); diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTService.java index 9ebd173a6..fc3569a6c 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTService.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTService.java @@ -50,10 +50,12 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; // Notes on running under Oreo // @@ -84,6 +86,7 @@ public class BTService extends XWJIService { XWJIService.register( BTService.class, sJobID, 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. private static int DEFAULT_KEEPALIVE_SECONDS = 15 * 60; @@ -166,10 +169,19 @@ public class BTService extends XWJIService { public static BluetoothAdapter getAdapterIf() { + BluetoothAdapter result = null; // Later this will change to include at least a test whether we're // running as background user account, a situation in which BT crashes // 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() @@ -184,6 +196,13 @@ public class BTService extends XWJIService { 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() { BluetoothAdapter adapter = getAdapterIf(); @@ -195,18 +214,14 @@ public class BTService extends XWJIService { public static String[] getBTNameAndAddress() { - BluetoothAdapter adapter = getAdapterIf(); - return null == adapter ? null - : new String[] { adapter.getName(), adapter.getAddress() }; - } - - public static int getPairedCount( Activity activity ) - { - int result = 0; + String[] result = null; BluetoothAdapter adapter = getAdapterIf(); if ( null != adapter ) { - Set pairedDevs = adapter.getBondedDevices(); - result = pairedDevs.size(); + String addr = adapter.getAddress(); + if ( isBogusAddr( addr ) ) { + addr = null; + } + result = new String[] { adapter.getName(), addr }; } return result; } @@ -357,8 +372,7 @@ public class BTService extends XWJIService { BluetoothAdapter adapter = getAdapterIf(); if ( null != adapter && adapter.isEnabled() ) { m_adapter = adapter; - Log.i( TAG, "onCreate(); bt name = %s; bt addr = %s", - adapter.getName(), adapter.getAddress() ); + Log.i( TAG, "onCreate(); my BT name: %s", adapter.getName() ); startListener(); } else { Log.w( TAG, "not starting threads: BT not available" ); @@ -565,6 +579,7 @@ public class BTService extends XWJIService { // listenUsingRfcommWithServiceRecord() in background (on // Android 9) m_serverSocket = null; + sBackUser.set( true ); // I'm seeing too much of this on two-user systems. // Log.ex( TAG, ex ); } @@ -681,7 +696,7 @@ public class BTService extends XWJIService { private static String getSafeAddr( CommsAddrRec addr ) { 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; if ( null == s_namesToAddrs ) { s_namesToAddrs = new HashMap<>(); @@ -692,16 +707,14 @@ public class BTService extends XWJIService { } else { btAddr = null; } - if ( null == btAddr ) { - BluetoothAdapter adapter = getAdapterIf(); - if ( null != adapter ) { - for ( BluetoothDevice dev : adapter.getBondedDevices() ) { - // Log.d( TAG, "%s => %s", dev.getName(), dev.getAddress() ); - if ( btName.equals( dev.getName() ) ) { - btAddr = dev.getAddress(); - s_namesToAddrs.put( btName, btAddr ); - break; - } + if ( TextUtils.isEmpty( btAddr ) ) { + Set devs = getCandidates(); + for ( BluetoothDevice dev : devs ) { + // Log.d( TAG, "%s => %s", dev.getName(), dev.getAddress() ); + if ( btName.equals( dev.getName() ) ) { + btAddr = dev.getAddress(); + s_namesToAddrs.put( btName, btAddr ); + break; } } } @@ -709,33 +722,34 @@ public class BTService extends XWJIService { return btAddr; } + public static Set getCandidates() + { + Set 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 ) { - Set pairedDevs = m_adapter.getBondedDevices(); + Set pairedDevs = getCandidates(); Map pas = new HashMap<>(); 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 = new PacketAccumulator( dev.getAddress(), timeoutMS ) .addPing( 0 ) @@ -1437,18 +1451,15 @@ public class BTService extends XWJIService { { Assert.assertFalse( BOGUS_MARSHMALLOW_ADDR.equals( addr ) ); String result = ""; - BluetoothAdapter adapter = getAdapterIf(); - if ( null != adapter ) { - Set devs = adapter.getBondedDevices(); - Iterator iter = devs.iterator(); - while ( iter.hasNext() ) { - BluetoothDevice dev = iter.next(); - String devAddr = dev.getAddress(); - Assert.assertFalse( BOGUS_MARSHMALLOW_ADDR.equals( devAddr ) ); - if ( devAddr.equals( addr ) ) { - result = dev.getName(); - break; - } + Set devs = getCandidates(); + Iterator iter = devs.iterator(); + while ( iter.hasNext() ) { + BluetoothDevice dev = iter.next(); + String devAddr = dev.getAddress(); + Assert.assertFalse( BOGUS_MARSHMALLOW_ADDR.equals( devAddr ) ); + if ( devAddr.equals( addr ) ) { + result = dev.getName(); + break; } } return result; @@ -1562,10 +1573,12 @@ public class BTService extends XWJIService { private static PacketAccumulator getSenderFor( String addr, boolean create ) { + Assert.assertTrueNR( ! BOGUS_MARSHMALLOW_ADDR.equals( addr ) ); PacketAccumulator result; try ( DeadlockWatch dw = new DeadlockWatch( sSenders ) ) { synchronized ( sSenders ) { if ( create && !sSenders.containsKey( addr ) ) { + // Log.d( TAG, "adding %s to senders", addr ); sSenders.put( addr, new PacketAccumulator( addr ) ); } result = sSenders.get( addr ); diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java index fbdb107b1..e5a117c1f 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java @@ -149,6 +149,7 @@ public abstract class DelegateBase implements DlgClickNotify, m_isVisible = true; XWServiceHelper.setListener( this ); runIfVisible(); + BTService.setAmForeground(); } protected void onPause() diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NetLaunchInfo.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NetLaunchInfo.java index 7b7f82b80..01dfb189f 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NetLaunchInfo.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/NetLaunchInfo.java @@ -450,8 +450,10 @@ public class NetLaunchInfo implements Serializable { } if ( addrs.contains( CommsConnType.COMMS_CONN_BT ) ) { - obj.put( MultiService.BT_NAME, btName ) - .put( MultiService.BT_ADDRESS, btAddress ); + obj.put( MultiService.BT_NAME, btName ); + if ( ! BTService.isBogusAddr( btAddress ) ) { + obj.put( MultiService.BT_ADDRESS, btAddress ); + } } if ( addrs.contains( CommsConnType.COMMS_CONN_SMS ) ) { obj.put( PHONE_KEY, phone ) @@ -539,7 +541,7 @@ public class NetLaunchInfo implements Serializable { case COMMS_CONN_BT: btAddress = json.optString( MultiService.BT_ADDRESS ); btName = json.optString( MultiService.BT_NAME ); - doAdd = !hasAddrs && !btAddress.isEmpty(); + doAdd = !hasAddrs && !btName.isEmpty(); break; case COMMS_CONN_RELAY: room = json.getString( MultiService.ROOM ); @@ -612,7 +614,9 @@ public class NetLaunchInfo implements Serializable { ub.appendQueryParameter( ID_KEY, inviteID ); } 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 ); } if ( addrs.contains( CommsConnType.COMMS_CONN_SMS ) ) { @@ -769,7 +773,7 @@ public class NetLaunchInfo implements Serializable { valid = null != room && null != inviteID(); break; case COMMS_CONN_BT: - valid = null != btAddress; + valid = null != btName; break; case COMMS_CONN_SMS: valid = null != phone && 0 < osVers; diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/CommsAddrRec.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/CommsAddrRec.java index 51b09d2dc..1bec5e9a0 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/CommsAddrRec.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/jni/CommsAddrRec.java @@ -338,7 +338,9 @@ public class CommsAddrRec implements java.io.Serializable { public void setBTParams( String btAddr, String btName ) { bt_hostName = btName; - bt_btAddr = btAddr; + if ( ! BTService.isBogusAddr( btAddr ) ) { + bt_btAddr = btAddr; + } } public void setSMSParams( String phone )