diff --git a/xwords4/android/app/src/main/AndroidManifest.xml b/xwords4/android/app/src/main/AndroidManifest.xml index db24701c9..ef8e0f2d7 100644 --- a/xwords4/android/app/src/main/AndroidManifest.xml +++ b/xwords4/android/app/src/main/AndroidManifest.xml @@ -25,6 +25,7 @@ + @@ -189,6 +190,7 @@ /> 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 f0277f0c7..4b984958a 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 @@ -191,6 +191,7 @@ public class BTService extends XWService { private BTSenderThread m_sender; private Notification m_notification; // make once use many private Handler mHandler; + private BTServiceHelper mHelper; private static int s_errCount = 0; @@ -418,6 +419,8 @@ public class BTService extends XWService { Log.d( TAG, "%s.onCreate()", this ); super.onCreate(); + mHelper = new BTServiceHelper( this ); + m_btMsgSink = new BTMsgSink(); mHandler = new Handler(); startForegroundIf(); @@ -522,7 +525,7 @@ public class BTService extends XWService { boolean cameOn = intent.getBooleanExtra( RADIO_KEY, false ); MultiEvent evt = cameOn? MultiEvent.BT_ENABLED : MultiEvent.BT_DISABLED; - postEvent( evt ); + mHelper.postEvent( evt ); if ( cameOn ) { GameUtils.resendAllIf( this, CommsConnType.COMMS_CONN_BT ); } else { @@ -581,6 +584,7 @@ public class BTService extends XWService { private BluetoothServerSocket m_serverSocket; private Context mContext; private BTService mService; + private BTServiceHelper mHelper; private volatile Thread mTimerThread; private BTListenerThread( Context context, BTService service ) @@ -595,7 +599,8 @@ public class BTService extends XWService { } } - static void startYourself( Context context, BTService service ) + static void startYourself( Context context, BTService service, + BTServiceHelper helper ) { Log.d( TAG, "startYourself(%s, %s)", context, service ); DbgUtils.assertOnUIThread(); @@ -604,7 +609,7 @@ public class BTService extends XWService { s_listener[0] = new BTListenerThread( context, service ); s_listener[0].start(); } else if ( null != service ) { - s_listener[0].setService( context, service ); + s_listener[0].setService( context, service, helper ); } } } @@ -612,7 +617,7 @@ public class BTService extends XWService { static void startYourself( Context context ) { DbgUtils.assertOnUIThread(); - startYourself( context, null ); + startYourself( context, null, null ); } static void stopYourself( BTListenerThread self ) @@ -634,11 +639,12 @@ public class BTService extends XWService { } } - void setService( Context context, BTService service ) + void setService( Context context, BTService service, BTServiceHelper helper ) { if ( null == mService ) { Log.d( TAG, "setService(): we didn't have one before. Do something!!!" ); mService = service; + mHelper = helper; Assert.assertNotNull( context ); mContext = context; // Use Service instead of Receiver (possibly) } else { @@ -838,16 +844,16 @@ public class BTService extends XWService { CommsAddrRec addr = new CommsAddrRec( host.getName(), host.getAddress() ); - ReceiveResult rslt - = mService.receiveMessage( mContext, - gameID, mService.m_btMsgSink, - buffer, addr ); + XWServiceHelper.ReceiveResult rslt + = mHelper.receiveMessage( mContext, + gameID, mService.m_btMsgSink, + buffer, addr ); - result = rslt == ReceiveResult.GAME_GONE ? + result = rslt == XWServiceHelper.ReceiveResult.GAME_GONE ? BTCmd.MESG_GAMEGONE : BTCmd.MESG_ACCPT; break; case MESG_GAMEGONE: - mService.postEvent( MultiEvent.MESSAGE_NOGAME, gameID ); + mHelper.postEvent( MultiEvent.MESSAGE_NOGAME, gameID ); result = BTCmd.MESG_ACCPT; break; default: @@ -977,7 +983,7 @@ public class BTService extends XWService { addrs.add( dev ); } if ( null != event ) { - postEvent( event, dev.getName() ); + mHelper.postEvent( event, dev.getName() ); } } } else { @@ -1010,7 +1016,7 @@ public class BTService extends XWService { } else { gotReply = BTCmd.PONG == reply; if ( gotReply && is.readBoolean() ) { - postEvent( MultiEvent.MESSAGE_NOGAME, gameID ); + mHelper.postEvent( MultiEvent.MESSAGE_NOGAME, gameID ); } } @@ -1064,20 +1070,24 @@ public class BTService extends XWService { } if ( null == reply ) { - postEvent( MultiEvent.APP_NOT_FOUND_BT, dev.getName() ); + mHelper.postEvent( MultiEvent.APP_NOT_FOUND_BT, + dev.getName() ); } else { switch ( reply ) { case BAD_PROTO: sendBadProto( socket ); break; case INVITE_ACCPT: - postEvent( MultiEvent.NEWGAME_SUCCESS, elem.m_gameID ); + mHelper.postEvent( MultiEvent.NEWGAME_SUCCESS, + elem.m_gameID ); break; case INVITE_DUPID: - postEvent( MultiEvent.NEWGAME_DUP_REJECTED, dev.getName() ); + mHelper.postEvent( MultiEvent.NEWGAME_DUP_REJECTED, + dev.getName() ); break; default: - postEvent( MultiEvent.NEWGAME_FAILURE, elem.m_gameID ); + mHelper.postEvent( MultiEvent.NEWGAME_FAILURE, + elem.m_gameID ); break; } } @@ -1160,10 +1170,10 @@ public class BTService extends XWService { if ( null != evt ) { String btName = nameForAddr( m_adapter, elem.m_btAddr ); - postEvent( evt, elem.m_gameID, 0, btName ); + mHelper.postEvent( evt, elem.m_gameID, 0, btName ); if ( ! success ) { int failCount = elem.incrFailCount(); - postEvent( MultiEvent.MESSAGE_RESEND, btName, + mHelper.postEvent( MultiEvent.MESSAGE_RESEND, btName, RESEND_TIMEOUT, failCount ); } } @@ -1183,7 +1193,7 @@ public class BTService extends XWService { iter.remove(); } else if ( elem.failCountExceeded() ) { String btName = nameForAddr( m_adapter, elem.m_btAddr ); - postEvent( MultiEvent.MESSAGE_FAILOUT, btName ); + mHelper.postEvent( MultiEvent.MESSAGE_FAILOUT, btName ); iter.remove(); } } @@ -1241,12 +1251,13 @@ public class BTService extends XWService { btNames[ii] = nameForAddr( m_adapter, btAddrs[ii] ); ++ii; } - postEvent( MultiEvent.SCAN_DONE, (Object)btAddrs, (Object)btNames ); + mHelper.postEvent( MultiEvent.SCAN_DONE, (Object)btAddrs, (Object)btNames ); } private void startListener() { - BTListenerThread.startYourself( this, this ); + Assert.assertNotNull( mHelper ); + BTListenerThread.startYourself( this, this, mHelper ); } private void startSender() @@ -1271,28 +1282,12 @@ public class BTService extends XWService { m_sender = null; } - @Override - void postNotification( String device, int gameID, long rowid ) - { - String body = LocUtils.getString( this, R.string.new_bt_body_fmt, - device ); - - GameUtils.postInvitedNotification( this, gameID, body, rowid ); - - postEvent( MultiEvent.BT_GAME_CREATED, rowid ); - } - - @Override - MultiMsgSink getSink( long rowid ) - { - return m_btMsgSink; - } - private BTCmd makeOrNotify( NetLaunchInfo nli, String btName, String btAddr ) { BTCmd result; - if ( handleInvitation( nli, btName, DictFetchOwner.OWNER_BT ) ) { // here + if ( mHelper.handleInvitation( nli, btName, + DictFetchOwner.OWNER_BT ) ) { result = BTCmd.INVITE_ACCPT; } else { result = BTCmd.INVITE_DUP_INVITE; // dupe of rematch @@ -1380,7 +1375,8 @@ public class BTService extends XWService { private void sendBadProto( BluetoothSocket socket ) { - postEvent( MultiEvent.BAD_PROTO_BT, socket.getRemoteDevice().getName() ); + mHelper.postEvent( MultiEvent.BAD_PROTO_BT, + socket.getRemoteDevice().getName() ); } private void updateStatusOut( boolean success ) @@ -1446,4 +1442,30 @@ public class BTService extends XWService { return nSent; } } + + private class BTServiceHelper extends XWServiceHelper { + private Service mService; + + BTServiceHelper( Service service ) { + super( service ); + mService = service; + } + + @Override + MultiMsgSink getSink( long rowid ) + { + return m_btMsgSink; + } + + @Override + void postNotification( String device, int gameID, long rowid ) + { + String body = LocUtils.getString( mService, R.string.new_bt_body_fmt, + device ); + + GameUtils.postInvitedNotification( mService, gameID, body, rowid ); + + postEvent( MultiEvent.BT_GAME_CREATED, rowid ); + } + } } 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 18564462b..0bd011297 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 @@ -143,14 +143,14 @@ public class DelegateBase implements DlgClickNotify, protected void onResume() { m_isVisible = true; - XWService.setListener( this ); + XWServiceHelper.setListener( this ); runIfVisible(); } protected void onPause() { m_isVisible = false; - XWService.setListener( null ); + XWServiceHelper.setListener( null ); } protected DelegateBase curThis() diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java index 4934b75d5..14e8a0b78 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java @@ -25,9 +25,9 @@ import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Handler; +import android.support.v4.app.JobIntentService; import android.text.TextUtils; - import org.eehouse.android.xw4.GameUtils.BackMoveResult; import org.eehouse.android.xw4.MultiService.DictFetchOwner; import org.eehouse.android.xw4.MultiService.MultiEvent; @@ -62,7 +62,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -public class RelayService extends XWService +public class RelayService extends JobIntentService implements NetStateCache.StateChangedIf { private static final String TAG = RelayService.class.getSimpleName(); private static final int MAX_SEND = 1024; @@ -121,6 +121,7 @@ public class RelayService extends XWService private long m_lastGamePacketReceived; private int m_nativeFailScore; private boolean m_skipUPDSet; + private RelayServiceHelper mHelper; private static DevIDType s_curType = DevIDType.ID_TYPE_NONE; private static long s_regStartTime = 0; @@ -221,20 +222,17 @@ public class RelayService extends XWService public static void startService( Context context ) { - Log.i( TAG, "startService()" ); Intent intent = getIntentTo( context, MsgCmds.UDP_CHANGED ); startService( context, intent ); } + // Must use the same lobID for all work enqueued for the same class + private final static int sJobID = RelayService.class.hashCode(); + private static void startService( Context context, Intent intent ) { - Log.d( TAG, "startService(%s)", intent ); - - if ( inForeground() || Build.VERSION.SDK_INT < Build.VERSION_CODES.O ) { - context.startService( intent ); - } else { - Log.d( TAG, "startService(); not starting" ); - } + Log.d( TAG, "startService(%s) (calling enqueueWork())", intent ); + enqueueWork( context, RelayService.class, sJobID, intent ); } private static void stopService( Context context ) @@ -308,18 +306,11 @@ public class RelayService extends XWService { Log.d( TAG, "receiveInvitation: got nli from %d: %s", srcDevID, nli.toString() ); - if ( !handleInvitation( nli, null, DictFetchOwner.OWNER_RELAY ) ) { + if ( !mHelper.handleInvitation( nli, null, DictFetchOwner.OWNER_RELAY ) ) { Log.d( TAG, "handleInvitation() failed" ); } } - @Override - void postNotification( String device, int gameID, long rowid ) - { - String body = LocUtils.getString( this, R.string.new_relay_body ); - GameUtils.postInvitedNotification( this, gameID, body, rowid ); - } - // Exists to get incoming data onto the main thread private static void postData( Context context, long rowid, byte[] msg ) { @@ -364,16 +355,12 @@ public class RelayService extends XWService return intent; } - @Override - protected MultiMsgSink getSink( long rowid ) - { - return new RelayMsgSink().setRowID( rowid ); - } - @Override public void onCreate() { + Log.d( TAG, "onCreate()" ); super.onCreate(); + mHelper = new RelayServiceHelper( this ); m_lastGamePacketReceived = XWPrefs.getPrefsLong( this, R.string.key_last_packet, Utils.getCurSeconds() ); @@ -398,6 +385,8 @@ public class RelayService extends XWService @Override public int onStartCommand( Intent intent, int flags, int startId ) { + Log.d( TAG, "onStartCommand(%s)", intent ); + super.onStartCommand( intent, flags, startId ); Integer result = handleCommand( intent ); if ( null == result ) { @@ -409,6 +398,13 @@ public class RelayService extends XWService return result; } + @Override + public void onHandleWork( Intent intent ) + { + Log.d( TAG, "onHandleWork(%s)", intent ); + /*void*/ handleCommand( intent ); + } + @Override public void onDestroy() { @@ -436,7 +432,7 @@ public class RelayService extends XWService cmd = null; } if ( null != cmd ) { - // Log.d( TAG, "onStartCommand(): cmd=%s", cmd.toString() ); + Log.d( TAG, "onStartCommand(): cmd=%s", cmd.toString() ); switch( cmd ) { case PROCESS_GAME_MSGS: String[] relayIDs = new String[1]; @@ -483,7 +479,7 @@ public class RelayService extends XWService String relayID = intent.getStringExtra( RELAY_ID ); sendNoConnMessage( rowid, relayID, msg ); } else { - receiveMessage( this, rowid, null, msg, s_addr ); + mHelper.receiveMessage( this, rowid, null, msg, s_addr ); } break; case INVITE: @@ -621,8 +617,6 @@ public class RelayService extends XWService private void stopUDPThreadsIf() { - DbgUtils.assertOnUIThread(); - UDPThreads threads = m_UDPThreadsRef.getAndSet( null ); if ( null != threads ) { threads.stop(); @@ -648,7 +642,7 @@ public class RelayService extends XWService Log.i( TAG, "relay unvailable for another %d seconds", unavail ); String str = getVLIString( dis ); - postEvent( MultiEvent.RELAY_ALERT, str ); + mHelper.postEvent( MultiEvent.RELAY_ALERT, str ); break; case XWPDEV_ALERT: str = getVLIString( dis ); @@ -999,7 +993,7 @@ public class RelayService extends XWService long rowid = rowIDs[ii]; sink.setRowID( rowid ); for ( byte[] msg : forOne ) { - receiveMessage( this, rowid, sink, msg, s_addr ); + mHelper.receiveMessage( this, rowid, sink, msg, s_addr ); } } } @@ -1728,6 +1722,28 @@ public class RelayService extends XWService } } + private class RelayServiceHelper extends XWServiceHelper { + + private Service mService; + RelayServiceHelper( Service service ) { + super( service ); + mService = service; + } + + @Override + protected MultiMsgSink getSink( long rowid ) + { + return new RelayMsgSink().setRowID( rowid ); + } + + @Override + void postNotification( String device, int gameID, long rowid ) + { + String body = LocUtils.getString( mService, R.string.new_relay_body ); + GameUtils.postInvitedNotification( mService, gameID, body, rowid ); + } + } + // Exits only to exist, so instanceof can distinguish private class EOQPacketData extends PacketData {} } diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/SMSService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/SMSService.java index eba26c22c..74500b81d 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/SMSService.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/SMSService.java @@ -86,6 +86,7 @@ public class SMSService extends XWService { private BroadcastReceiver m_sentReceiver; private BroadcastReceiver m_receiveReceiver; private OnSharedPreferenceChangeListener m_prefsListener; + private SMSServiceHelper mHelper; private int m_nReceived = 0; private static int s_nSent = 0; @@ -277,15 +278,10 @@ public class SMSService extends XWService { return s_showToasts; } - @Override - protected MultiMsgSink getSink( long rowid ) - { - return new SMSMsgSink( this ); - } - @Override public void onCreate() { + mHelper = new SMSServiceHelper( this ); if ( Utils.deviceSupportsSMS( this ) ) { registerReceivers(); } else { @@ -469,10 +465,10 @@ public class SMSService extends XWService { } break; case DEATH: - postEvent( MultiEvent.MESSAGE_NOGAME, msg.gameID ); + mHelper.postEvent( MultiEvent.MESSAGE_NOGAME, msg.gameID ); break; case ACK_INVITE: - postEvent( MultiEvent.NEWGAME_SUCCESS, msg.gameID ); + mHelper.postEvent( MultiEvent.NEWGAME_SUCCESS, msg.gameID ); break; default: Log.w( TAG, "unexpected cmd %s", msg.cmd ); @@ -489,26 +485,17 @@ public class SMSService extends XWService { for ( SMSProtoMsg msg : msgs ) { receive( msg, senderPhone ); } - postEvent( MultiEvent.SMS_RECEIVE_OK ); + mHelper.postEvent( MultiEvent.SMS_RECEIVE_OK ); } else { Log.d( TAG, "receiveBuffer(): bogus or incomplete message from %s", senderPhone ); } } - @Override - protected void postNotification( String phone, int gameID, long rowid ) - { - String owner = Utils.phoneToContact( this, phone, true ); - String body = LocUtils.getString( this, R.string.new_name_body_fmt, - owner ); - GameUtils.postInvitedNotification( this, gameID, body, rowid ); - } - private void makeForInvite( String phone, NetLaunchInfo nli ) { if ( nli != null ) { - handleInvitation( nli, phone, DictFetchOwner.OWNER_SMS ); + mHelper.handleInvitation( nli, phone, DictFetchOwner.OWNER_SMS ); ackInvite( phone, nli.gameID() ); } } @@ -554,7 +541,7 @@ public class SMSService extends XWService { } catch ( NullPointerException npe ) { Assert.fail(); // shouldn't be trying to do this!!! } catch ( java.lang.SecurityException se ) { - postEvent( MultiEvent.SMS_SEND_FAILED_NOPERMISSION ); + mHelper.postEvent( MultiEvent.SMS_SEND_FAILED_NOPERMISSION ); } catch ( Exception ee ) { Log.ex( TAG, ee ); } @@ -575,11 +562,12 @@ public class SMSService extends XWService { private boolean feedMessage( int gameID, byte[] msg, CommsAddrRec addr ) { - ReceiveResult rslt = receiveMessage( this, gameID, null, msg, addr ); - if ( ReceiveResult.GAME_GONE == rslt ) { + XWServiceHelper.ReceiveResult rslt = mHelper + .receiveMessage( this, gameID, null, msg, addr ); + if ( XWServiceHelper.ReceiveResult.GAME_GONE == rslt ) { sendDiedPacket( addr.sms_phone, gameID ); } - return rslt == ReceiveResult.OK; + return rslt == XWServiceHelper.ReceiveResult.OK; } private void registerReceivers() @@ -590,15 +578,15 @@ public class SMSService extends XWService { { switch ( getResultCode() ) { case Activity.RESULT_OK: - postEvent( MultiEvent.SMS_SEND_OK ); + mHelper.postEvent( MultiEvent.SMS_SEND_OK ); break; case SmsManager.RESULT_ERROR_RADIO_OFF: - postEvent( MultiEvent.SMS_SEND_FAILED_NORADIO ); + mHelper.postEvent( MultiEvent.SMS_SEND_FAILED_NORADIO ); break; case SmsManager.RESULT_ERROR_NO_SERVICE: default: Log.w( TAG, "FAILURE!!!" ); - postEvent( MultiEvent.SMS_SEND_FAILED ); + mHelper.postEvent( MultiEvent.SMS_SEND_FAILED ); break; } } @@ -655,4 +643,28 @@ public class SMSService extends XWService { return sendPacket( addr.sms_phone, gameID, buf ); } } + + private class SMSServiceHelper extends XWServiceHelper { + private Service mService; + + SMSServiceHelper( Service service ) { + super( service ); + mService = service; + } + + @Override + protected MultiMsgSink getSink( long rowid ) + { + return new SMSMsgSink( SMSService.this ); + } + + @Override + protected void postNotification( String phone, int gameID, long rowid ) + { + String owner = Utils.phoneToContact( mService, phone, true ); + String body = LocUtils.getString( mService, R.string.new_name_body_fmt, + owner ); + GameUtils.postInvitedNotification( mService, gameID, body, rowid ); + } + } } diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/WiDirService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/WiDirService.java index 600c03770..432d191b9 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/WiDirService.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/WiDirService.java @@ -124,6 +124,7 @@ public class WiDirService extends XWService { private static Set s_peersSet; private P2pMsgSink m_sink; + private WiDirServiceHelper mHelper; public interface DevSetListener { void setChanged( Map macToName ); @@ -133,6 +134,7 @@ public class WiDirService extends XWService { public void onCreate() { m_sink = new P2pMsgSink(); + mHelper = new WiDirServiceHelper(this); } @Override @@ -751,8 +753,9 @@ public class WiDirService extends XWService { CommsAddrRec addr = new CommsAddrRec( CommsConnType.COMMS_CONN_P2P ) .setP2PParams( macAddress ); - ReceiveResult rslt = receiveMessage( this, gameID, m_sink, data, addr ); - if ( ReceiveResult.GAME_GONE == rslt ) { + XWServiceHelper.ReceiveResult rslt = mHelper + .receiveMessage( this, gameID, m_sink, data, addr ); + if ( XWServiceHelper.ReceiveResult.GAME_GONE == rslt ) { sendNoGame( null, macAddress, gameID ); } } @@ -764,27 +767,15 @@ public class WiDirService extends XWService { NetLaunchInfo nli = NetLaunchInfo.makeFrom( this, nliData ); String returnMac = intent.getStringExtra( KEY_SRC ); - if ( !handleInvitation( nli, returnMac, DictFetchOwner.OWNER_P2P ) ) { + if ( !mHelper.handleInvitation( nli, returnMac, DictFetchOwner.OWNER_P2P ) ) { Log.d( TAG, "handleInvitation() failed" ); } } - @Override - void postNotification( String device, int gameID, long rowid ) - { - Log.e( TAG, "postNotification() doing nothing" ); - } - - @Override - MultiMsgSink getSink( long rowid ) - { - return m_sink; - } - private void handleGameGone( Intent intent ) { int gameID = intent.getIntExtra( KEY_GAMEID, 0 ); - postEvent( MultiEvent.MESSAGE_NOGAME, gameID ); + mHelper.postEvent( MultiEvent.MESSAGE_NOGAME, gameID ); } private void makeGame( NetLaunchInfo nli, String senderMac ) @@ -794,7 +785,7 @@ public class WiDirService extends XWService { CommsAddrRec addr = nli.makeAddrRec( this ); long rowid = GameUtils.makeNewMultiGame( this, nli, m_sink, - getUtilCtxt() ); + mHelper.getUtilCtxt() ); if ( DBUtils.ROWID_NOTFOUND != rowid ) { if ( null != nli.gameName && 0 < nli.gameName.length() ) { DBUtils.setName( this, rowid, nli.gameName ); @@ -1206,4 +1197,23 @@ public class WiDirService extends XWService { private class P2pMsgSink extends MultiMsgSink { public P2pMsgSink() { super( WiDirService.this ); } } + + private class WiDirServiceHelper extends XWServiceHelper { + + WiDirServiceHelper( Service service ) { + super( service ); + } + + @Override + MultiMsgSink getSink( long rowid ) + { + return m_sink; + } + + @Override + void postNotification( String device, int gameID, long rowid ) + { + Log.e( TAG, "postNotification() doing nothing" ); + } + } } diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWService.java index 4e431f2c0..c995ba897 100644 --- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWService.java +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWService.java @@ -1,6 +1,6 @@ /* -*- compile-command: "find-and-gradle.sh insXw4Deb"; -*- */ /* - * Copyright 2010 - 2012 by Eric House (xwords@eehouse.org). All + * Copyright 2010 - 2018 by Eric House (xwords@eehouse.org). All * rights reserved. * * This program is free software; you can redistribute it and/or @@ -21,166 +21,15 @@ package org.eehouse.android.xw4; import android.app.Service; -import android.content.Context; import android.content.Intent; import android.os.IBinder; - -import org.eehouse.android.xw4.MultiService.DictFetchOwner; -import org.eehouse.android.xw4.MultiService.MultiEvent; -import org.eehouse.android.xw4.jni.CommsAddrRec; -import org.eehouse.android.xw4.jni.JNIThread; -import org.eehouse.android.xw4.jni.UtilCtxt; -import org.eehouse.android.xw4.jni.UtilCtxtImpl; - -import java.util.HashMap; -import java.util.Map; - -abstract class XWService extends Service { +class XWService extends Service { private static final String TAG = XWService.class.getSimpleName(); - public static enum ReceiveResult { OK, GAME_GONE, UNCONSUMED }; - - protected static MultiService s_srcMgr = null; - private static Map s_seen = new HashMap<>(); - - private UtilCtxt m_utilCtxt; @Override public IBinder onBind( Intent intent ) { return null; } - - public final static void setListener( MultiService.MultiEventListener li ) - { - if ( null == s_srcMgr ) { - // DbgUtils.logf( "XWService.setListener: registering %s", li.getClass().getName() ); - s_srcMgr = new MultiService(); - } - s_srcMgr.setListener( li ); - } - - protected void postEvent( MultiEvent event, Object ... args ) - { - if ( null != s_srcMgr ) { - s_srcMgr.postEvent( event, args ); - } else { - Log.d( TAG, "postEvent(): dropping %s event", - event.toString() ); - } - } - - // Check that we aren't already processing an invitation with this - // inviteID. - private static final long SEEN_INTERVAL_MS = 1000 * 5; - private boolean checkNotDupe( NetLaunchInfo nli ) - { - String inviteID = nli.inviteID(); - synchronized( s_seen ) { - long now = System.currentTimeMillis(); - Long lastSeen = s_seen.get( inviteID ); - boolean seen = null != lastSeen && lastSeen + SEEN_INTERVAL_MS > now; - if ( !seen ) { - s_seen.put( inviteID, now ); - } - Log.d( TAG, "checkNotDupe('%s') => %b", inviteID, !seen ); - return !seen; - } - } - - abstract void postNotification( String device, int gameID, long rowid ); - - // Return true if able to start game only - protected boolean handleInvitation( NetLaunchInfo nli, String device, - DictFetchOwner dfo ) - { - boolean success = false; - long[] rowids = DBUtils.getRowIDsFor( this, nli.gameID() ); - if ( 0 == rowids.length - || ( rowids.length < nli.nPlayersT // will break for two-per-device game - && XWPrefs.getSecondInviteAllowed( this ) ) ) { - - if ( nli.isValid() && checkNotDupe( nli ) ) { - - if ( DictLangCache.haveDict( this, nli.lang, nli.dict ) ) { - long rowid = GameUtils.makeNewMultiGame( this, nli, - getSink( 0 ), - getUtilCtxt() ); - - if ( null != nli.gameName && 0 < nli.gameName.length() ) { - DBUtils.setName( this, rowid, nli.gameName ); - } - - postNotification( device, nli.gameID(), rowid ); - success = true; - } else { - Intent intent = MultiService - .makeMissingDictIntent( this, nli, dfo ); - MultiService.postMissingDictNotification( this, intent, - nli.gameID() ); - } - } - } - Log.d( TAG, "handleInvitation() => %b", success ); - return success; - } - - protected UtilCtxt getUtilCtxt() - { - if ( null == m_utilCtxt ) { - m_utilCtxt = new UtilCtxtImpl( this ); - } - return m_utilCtxt; - } - - // Meant to be overridden - abstract MultiMsgSink getSink( long rowid ); - - protected ReceiveResult receiveMessage( Context context, int gameID, - MultiMsgSink sink, byte[] msg, - CommsAddrRec addr ) - { - ReceiveResult result; - long[] rowids = DBUtils.getRowIDsFor( context, gameID ); - if ( null == rowids || 0 == rowids.length ) { - result = ReceiveResult.GAME_GONE; - } else { - result = ReceiveResult.UNCONSUMED; - for ( long rowid : rowids ) { - if ( receiveMessage( context, rowid, sink, msg, addr ) ) { - result = ReceiveResult.OK; - } - } - } - return result; - } - - protected boolean receiveMessage( Context context, long rowid, - MultiMsgSink sink, byte[] msg, - CommsAddrRec addr ) - { - boolean allConsumed = true; - boolean[] isLocalP = new boolean[1]; - JNIThread jniThread = JNIThread.getRetained( rowid, false ); - boolean consumed = false; - if ( null != jniThread ) { - consumed = true; - jniThread.receive( msg, addr ).release(); - } else { - GameUtils.BackMoveResult bmr = new GameUtils.BackMoveResult(); - if ( null == sink ) { - sink = getSink( rowid ); - } - if ( GameUtils.feedMessage( context, rowid, msg, addr, - sink, bmr, isLocalP ) ) { - consumed = true; - GameUtils.postMoveNotification( context, rowid, bmr, - isLocalP[0] ); - } - } - if ( allConsumed && !consumed ) { - allConsumed = false; - } - return allConsumed; - } } diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWServiceHelper.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWServiceHelper.java new file mode 100644 index 000000000..e23a85349 --- /dev/null +++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWServiceHelper.java @@ -0,0 +1,182 @@ +/* -*- compile-command: "find-and-gradle.sh insXw4Deb"; -*- */ +/* + * Copyright 2010 - 2018 by Eric House (xwords@eehouse.org). All + * rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package org.eehouse.android.xw4; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; + +import org.eehouse.android.xw4.MultiService.DictFetchOwner; +import org.eehouse.android.xw4.MultiService.MultiEvent; +import org.eehouse.android.xw4.jni.CommsAddrRec; +import org.eehouse.android.xw4.jni.JNIThread; +import org.eehouse.android.xw4.jni.UtilCtxt; +import org.eehouse.android.xw4.jni.UtilCtxtImpl; + +import java.util.HashMap; +import java.util.Map; + + +abstract class XWServiceHelper { + private static final String TAG = XWServiceHelper.class.getSimpleName(); + private Service mService; + private static MultiService s_srcMgr = null; + + public static enum ReceiveResult { OK, GAME_GONE, UNCONSUMED }; + + XWServiceHelper( Service service ) + { + mService = service; + } + + abstract MultiMsgSink getSink( long rowid ); + abstract void postNotification( String device, int gameID, long rowid ); + + protected ReceiveResult receiveMessage( Context context, int gameID, + MultiMsgSink sink, byte[] msg, + CommsAddrRec addr ) + { + ReceiveResult result; + long[] rowids = DBUtils.getRowIDsFor( context, gameID ); + if ( null == rowids || 0 == rowids.length ) { + result = ReceiveResult.GAME_GONE; + } else { + result = ReceiveResult.UNCONSUMED; + for ( long rowid : rowids ) { + if ( receiveMessage( context, rowid, sink, msg, addr ) ) { + result = ReceiveResult.OK; + } + } + } + return result; + } + + protected boolean receiveMessage( Context context, long rowid, + MultiMsgSink sink, byte[] msg, + CommsAddrRec addr ) + { + boolean allConsumed = true; + boolean[] isLocalP = new boolean[1]; + JNIThread jniThread = JNIThread.getRetained( rowid, false ); + boolean consumed = false; + if ( null != jniThread ) { + consumed = true; + jniThread.receive( msg, addr ).release(); + } else { + GameUtils.BackMoveResult bmr = new GameUtils.BackMoveResult(); + if ( null == sink ) { + sink = getSink( rowid ); + } + if ( GameUtils.feedMessage( context, rowid, msg, addr, + sink, bmr, isLocalP ) ) { + consumed = true; + GameUtils.postMoveNotification( context, rowid, bmr, + isLocalP[0] ); + } + } + if ( allConsumed && !consumed ) { + allConsumed = false; + } + return allConsumed; + } + + public final static void setListener( MultiService.MultiEventListener li ) + { + if ( null == s_srcMgr ) { + // DbgUtils.logf( "XWService.setListener: registering %s", + // li.getClass().getName() ); + s_srcMgr = new MultiService(); + } + s_srcMgr.setListener( li ); + } + + protected void postEvent( MultiEvent event, Object ... args ) + { + if ( null != s_srcMgr ) { + s_srcMgr.postEvent( event, args ); + } else { + Log.d( TAG, "postEvent(): dropping %s event", + event.toString() ); + } + } + + protected boolean handleInvitation( NetLaunchInfo nli, String device, + DictFetchOwner dfo ) + { + boolean success = false; + long[] rowids = DBUtils.getRowIDsFor( mService, nli.gameID() ); + if ( 0 == rowids.length + || ( rowids.length < nli.nPlayersT // will break for two-per-device game + && XWPrefs.getSecondInviteAllowed( mService ) ) ) { + + if ( nli.isValid() && checkNotDupe( nli ) ) { + + if ( DictLangCache.haveDict( mService, nli.lang, nli.dict ) ) { + long rowid = GameUtils.makeNewMultiGame( mService, nli, + getSink( 0 ), + getUtilCtxt() ); + + if ( null != nli.gameName && 0 < nli.gameName.length() ) { + DBUtils.setName( mService, rowid, nli.gameName ); + } + + postNotification( device, nli.gameID(), rowid ); + success = true; + } else { + Intent intent = MultiService + .makeMissingDictIntent( mService, nli, dfo ); + MultiService.postMissingDictNotification( mService, intent, + nli.gameID() ); + } + } + } + Log.d( TAG, "handleInvitation() => %b", success ); + return success; + } + + private UtilCtxt m_utilCtxt; + protected UtilCtxt getUtilCtxt() + { + if ( null == m_utilCtxt ) { + m_utilCtxt = new UtilCtxtImpl( mService ); + } + return m_utilCtxt; + } + + // Check that we aren't already processing an invitation with this + // inviteID. + private static final long SEEN_INTERVAL_MS = 1000 * 5; + private static Map s_seen = new HashMap<>(); + private boolean checkNotDupe( NetLaunchInfo nli ) + { + String inviteID = nli.inviteID(); + synchronized( s_seen ) { + long now = System.currentTimeMillis(); + Long lastSeen = s_seen.get( inviteID ); + boolean seen = null != lastSeen && lastSeen + SEEN_INTERVAL_MS > now; + if ( !seen ) { + s_seen.put( inviteID, now ); + } + Log.d( TAG, "checkNotDupe('%s') => %b", inviteID, !seen ); + return !seen; + } + } +}