beginning of android changes to talk udp to the relay: sufficient to

get back (and log, not display) a message when the relay is in
maintenance mode.
This commit is contained in:
Eric House 2013-01-20 15:29:51 -08:00
parent 93ff4f4fcb
commit fd2f4309f4
6 changed files with 269 additions and 11 deletions

View file

@ -41,6 +41,7 @@ public class PrefsActivity extends PreferenceActivity
private String m_keyLogging;
private String m_smsToasting;
private String m_smsEnable;
private String m_udpEnabled;
private String m_downloadPath;
@Override
@ -122,6 +123,7 @@ public class PrefsActivity extends PreferenceActivity
m_keyLogging = getString( R.string.key_logging_on );
m_smsToasting = getString( R.string.key_show_sms );
m_smsEnable = getString( R.string.key_enable_sms );
m_udpEnabled = getString( R.string.key_udp_relay );
m_downloadPath = getString( R.string.key_download_path );
Button button = (Button)findViewById( R.id.revert_colors );
@ -161,6 +163,8 @@ public class PrefsActivity extends PreferenceActivity
DbgUtils.logEnable( sp.getBoolean( key, false ) );
} else if ( key.equals( m_smsToasting ) ) {
SMSService.smsToastEnable( sp.getBoolean( key, false ) );
} else if ( key.equals( m_udpEnabled ) ) {
RelayService.udpChanged( this );
} else if ( key.equals( m_smsEnable ) ) {
if ( sp.getBoolean( key, true ) ) {
SMSService.checkForInvites( this );

View file

@ -24,31 +24,66 @@ import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.LinkedBlockingQueue;
import junit.framework.Assert;
import org.eehouse.android.xw4.jni.GameSummary;
import org.eehouse.android.xw4.jni.UtilCtxt;
public class RelayService extends Service {
private static final int MAX_SEND = 1024;
private static final int MAX_BUF = MAX_SEND - 2;
private static final String CMD_STR = "CMD";
private static final int UDP_CHANGED = 1;
private Thread m_fetchThread = null;
private Thread m_UDPReadThread = null;
private Thread m_UDPWriteThread = null;
private DatagramSocket m_UDPSocket;
private LinkedBlockingQueue<DatagramPacket> m_queue = null;
// These must match the enum XWRelayReg in xwrelay.h
private static final int XWPDEV_PROTO_VERSION = 0;
// private static final int XWPDEV_NONE = 0;
private static final int XWPDEV_ALERT = 1;
private static final int XWPDEV_REG = 2;
public static void startService( Context context )
{
Intent intent = getIntentTo( context, UDP_CHANGED );
context.startService( intent );
}
public static void udpChanged( Context context )
{
startService( context );
}
private static Intent getIntentTo( Context context, int cmd )
{
Intent intent = new Intent( context, RelayService.class );
intent.putExtra( CMD_STR, cmd );
return intent;
}
@Override
public void onCreate()
{
super.onCreate();
Thread thread = new Thread( null, new Runnable() {
public void run() {
fetchAndProcess();
RelayService.this.stopSelf();
}
}, getClass().getName() );
thread.start();
startFetchThreadIf();
}
@Override
@ -57,6 +92,36 @@ public class RelayService extends Service {
return null;
}
@Override
public int onStartCommand( Intent intent, int flags, int startId )
{
DbgUtils.logf( "RelayService::onStartCommand" );
int result;
if ( null != intent ) {
int cmd = intent.getIntExtra( CMD_STR, -1 );
switch( cmd ) {
case UDP_CHANGED:
DbgUtils.logf( "RelayService::onStartCommand::UDP_CHANGED" );
if ( XWPrefs.getUDPEnabled( this ) ) {
stopFetchThreadIf();
startUDPThreads();
registerWithRelay();
} else {
stopUDPThreadsIf();
startFetchThreadIf();
}
break;
default:
Assert.fail();
}
result = Service.START_STICKY;
} else {
result = Service.START_STICKY_COMPATIBILITY;
}
return result;
}
private void setupNotification( String[] relayIDs )
{
for ( String relayID : relayIDs ) {
@ -75,6 +140,189 @@ public class RelayService extends Service {
}
}
private void startFetchThreadIf()
{
DbgUtils.logf( "startFetchThreadIf()" );
if ( !XWPrefs.getUDPEnabled( this ) && null == m_fetchThread ) {
m_fetchThread = new Thread( null, new Runnable() {
public void run() {
fetchAndProcess();
m_fetchThread = null;
RelayService.this.stopSelf();
}
}, getClass().getName() );
m_fetchThread.start();
}
}
private void stopFetchThreadIf()
{
if ( null != m_fetchThread ) {
DbgUtils.logf( "2: m_fetchThread NOT NULL; WHAT TO DO???" );
}
}
private void startUDPThreads()
{
DbgUtils.logf( "startUDPThreads" );
Assert.assertNull( m_UDPWriteThread );
Assert.assertNull( m_UDPReadThread );
Assert.assertTrue( XWPrefs.getUDPEnabled( this ) );
int port = XWPrefs.getDefaultRelayPort( RelayService.this );
String host = XWPrefs.getDefaultRelayHost( RelayService.this );
try {
m_UDPSocket = new DatagramSocket();
InetAddress addr = InetAddress.getByName( host );
m_UDPSocket.connect( addr, port );
} catch( java.net.SocketException se ) {
DbgUtils.loge( se );
Assert.fail();
} catch( java.net.UnknownHostException uhe ) {
DbgUtils.loge( uhe );
}
m_UDPReadThread = new Thread( null, new Runnable() {
public void run() {
byte[] buf = new byte[1024];
for ( ; ; ) {
DatagramPacket packet =
new DatagramPacket( buf, buf.length );
try {
DbgUtils.logf( "UPD read thread blocking on receive" );
m_UDPSocket.receive( packet );
DbgUtils.logf( "UPD read thread: receive returned" );
} catch( java.io.IOException ioe ) {
DbgUtils.loge( ioe );
break; // ???
}
DbgUtils.logf( "received %d bytes", packet.getLength() );
gotPacket( packet );
}
}
}, getClass().getName() );
m_UDPReadThread.start();
m_queue = new LinkedBlockingQueue<DatagramPacket>();
m_UDPWriteThread = new Thread( null, new Runnable() {
public void run() {
for ( ; ; ) {
DatagramPacket outPacket;
try {
outPacket = m_queue.take();
} catch ( InterruptedException ie ) {
DbgUtils.logf( "RelayService; write thread killed" );
break;
}
if ( null == outPacket || 0 == outPacket.getLength() ) {
DbgUtils.logf( "stopping write thread" );
break;
}
DbgUtils.logf( "Sending packet of length %d",
outPacket.getLength() );
try {
m_UDPSocket.send( outPacket );
} catch ( java.io.IOException ioe ) {
DbgUtils.loge( ioe );
}
}
}
}, getClass().getName() );
m_UDPWriteThread.start();
}
private void stopUDPThreadsIf()
{
DbgUtils.logf( "stopUDPThreadsIf" );
if ( null != m_queue && null != m_UDPWriteThread ) {
// can't add null
m_queue.add( new DatagramPacket( new byte[0], 0 ) );
try {
DbgUtils.logf( "joining m_UDPWriteThread" );
m_UDPWriteThread.join();
DbgUtils.logf( "SUCCESSFULLY joined m_UDPWriteThread" );
} catch( java.lang.InterruptedException ie ) {
DbgUtils.loge( ie );
}
m_UDPWriteThread = null;
m_queue = null;
}
if ( null != m_UDPSocket && null != m_UDPReadThread ) {
m_UDPSocket.close();
DbgUtils.logf( "waiting for read thread to exit" );
try {
m_UDPReadThread.join();
} catch( java.lang.InterruptedException ie ) {
DbgUtils.loge( ie );
}
DbgUtils.logf( "read thread exited" );
m_UDPReadThread = null;
m_UDPSocket = null;
}
DbgUtils.logf( "stopUDPThreadsIf DONE" );
}
private void gotPacket( DatagramPacket packet )
{
DbgUtils.logf( "gotPacket" );
ByteArrayInputStream bis = new ByteArrayInputStream( packet.getData() );
DataInputStream dis = new DataInputStream( bis );
try {
byte proto = dis.readByte();
if ( XWPDEV_PROTO_VERSION == proto ) {
byte cmd = dis.readByte();
switch ( cmd ) {
case XWPDEV_ALERT:
short len = dis.readShort();
byte[] tmp = new byte[len];
dis.read( tmp );
String msg = new String( tmp );
DbgUtils.logf( "got message: %s", msg );
break;
default:
DbgUtils.logf( "RelayService: Unhandled cmd: %d", cmd );
break;
}
} else {
DbgUtils.logf( "bad proto %d", proto );
}
} catch ( java.io.IOException ioe ) {
DbgUtils.loge( ioe );
}
}
private void registerWithRelay()
{
byte typ;
String devid = XWPrefs.getRelayDevID( this );
if ( null != devid && 0 < devid.length() ) {
typ = UtilCtxt.ID_TYPE_RELAY;
} else {
devid = XWPrefs.getGCMDevID( this );
if ( null != devid && 0 < devid.length() ) {
typ = UtilCtxt.ID_TYPE_ANDROID_GCM;
} else {
devid = "DO NOT SHIP WITH ME";
typ = UtilCtxt.ID_TYPE_ANDROID_OTHER;
}
}
ByteArrayOutputStream bas = new ByteArrayOutputStream();
DataOutputStream outBuf = new DataOutputStream( bas );
try {
outBuf.writeByte( XWPDEV_PROTO_VERSION );
outBuf.writeByte( XWPDEV_REG );
outBuf.writeByte( typ );
outBuf.writeShort( devid.length() );
outBuf.writeBytes( devid );
byte[] data = bas.toByteArray();
m_queue.add( new DatagramPacket( data, data.length ) );
} catch ( java.io.IOException ioe ) {
DbgUtils.loge( ioe );
}
}
private void fetchAndProcess()
{
long[][] rowIDss = new long[1][];

View file

@ -66,7 +66,7 @@ public class SMSService extends Service {
private static final int INVITE = 2;
private static final int SEND = 3;
private static final int REMOVE = 4;
private static final int MESG_GAMEGONE = 5;
// private static final int MESG_GAMEGONE = 5;
private static final int CHECK_MSGDB = 6;
private static final int ADDED_MISSING = 7;

View file

@ -58,10 +58,10 @@ public class XWApp extends Application {
RelayReceiver.RestartTimer( this );
UpdateCheckReceiver.restartTimer( this );
BTService.startService( this );
SMSService.checkForInvites( this );
RelayService.startService( this );
GCMIntentService.init( this );
}

View file

@ -34,6 +34,11 @@ public class XWPrefs {
return getPrefsBoolean( context, R.string.key_enable_sms, false );
}
public static boolean getUDPEnabled( Context context )
{
return getPrefsBoolean( context, R.string.key_udp_relay, false );
}
public static boolean getDebugEnabled( Context context )
{
return getPrefsBoolean( context, R.string.key_enable_debug, false );

View file

@ -60,6 +60,7 @@ public interface UtilCtxt {
public static final int ID_TYPE_NONE = 0;
public static final int ID_TYPE_RELAY = 1;
public static final int ID_TYPE_ANDROID_GCM = 3;
public static final int ID_TYPE_ANDROID_OTHER = 4;
String getDevID( /*out*/ byte[] typ );
void deviceRegistered( int devIDType, String idRelay );