Android Open Source - clash_of_balls Networking






From Project

Back to project page clash_of_balls.

License

The source code is released under:

GNU General Public License

If you think the Android project clash_of_balls listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright 2010-2011, Qualcomm Innovation Center, Inc.
 */* w w w . j av a2  s. com*/
 * this code was taken from the Chat sample application in the AllJoyn library
 * and modified by:
 * 2013 Beat Kng <beat-kueng@gmx.net>
 * 
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 * 
 *        http://www.apache.org/licenses/LICENSE-2.0
 * 
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.sapos_aplastados.game.clash_of_balls.network;

import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.alljoyn.bus.BusAttachment;
import org.alljoyn.bus.BusException;
import org.alljoyn.bus.BusListener;
import org.alljoyn.bus.BusObject;
import org.alljoyn.bus.MessageContext;
import org.alljoyn.bus.Mutable;
import org.alljoyn.bus.SessionListener;
import org.alljoyn.bus.SessionOpts;
import org.alljoyn.bus.SessionPortListener;
import org.alljoyn.bus.SignalEmitter;
import org.alljoyn.bus.Status;
import org.alljoyn.bus.annotation.BusSignal;
import org.alljoyn.bus.annotation.BusSignalHandler;

import com.sapos_aplastados.game.clash_of_balls.game.Vector;

import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

/**
 * thread-safe networking interface to use AllJoyn
 * 
 * incoming messages are queued. get them with the receive* methods.
 * a call to receive* will remove the message from the queue.
 * call registerEventListener to get notifications on receive updates.
 * 
 * call setServerName before calling startAdvertise or joinSession
 * 
 * Note that AllJoyn has a maximum packet size of 2^17 bytes
 * (BusAttachment.ALLJOYN_MAX_PACKET_LEN)
 *
 * for every receive* method there must be someone to call them, because
 * otherwise the queue will fill up and use more and more memory
 * 
 * this is a singleton class
 */
public class Networking {
  private static final String TAG = "Networking";
  
  public static final int protocol_version = 1; //if another endpoint
      //uses another version, they cannot communicate with each other
  
  private Context m_context;
  private boolean m_bInit=false;
  
  private Networking() {}
  private static Networking m_instance;
  
  public static Networking getInstance() {
    if(m_instance==null) m_instance=new Networking();
    return m_instance;
  }
  
  public synchronized void init(Context context) {
    if(m_bInit) return;
    Log.d(TAG, "init Network Object");
    //clear connected clients
    m_connected_clients = new ArrayList<ConnectedClient>();
    m_context = context;
    if(mBus == null)
      mBus = new BusAttachment(context.getPackageName()
          , BusAttachment.RemoteMessage.Receive);
    m_network_service = new NetworkService();
    startBusThread();
    m_background_handler.connect();
    m_bInit=true;
  }
  public void deinit() {
    if(!m_bInit) return;
    Log.d(TAG, "deinit Network Object");
    if(isBusConnected()) {
      m_background_handler.leaveSession();
      m_background_handler.cancelAdvertise();
      m_background_handler.unbindSession();
      m_background_handler.releaseName();
      m_background_handler.disconnect();
    }
    stopBusThread();
    m_bInit=false;
  }
  
  /* public interface */
  
  /* sending messages */
  public void sendSensorUpdate(Vector pos) 
      throws BusException {
    try {
      if (mJoinedToSelf) {
        //this signal is: client --> server. so don't send to clients
        //if (mHostChatInterface != null) 
        //  mHostChatInterface.sensorUpdate(pos);
        receivedSensorUpdate(m_bus_unique_name, pos.x, pos.y); //send to ourself
      } else {
        if(mChatInterface!=null) mChatInterface.sensorUpdate(pos.x, pos.y);
      }
    } catch (BusException ex) {
        alljoynError(Module.USE, AllJoynError.SEND_ERROR, 
            "Bus exception while sending message: (" + ex + ")");
    }
  }
    public void sendGameCommand(byte[] data) throws BusException {
    try {
      if (mJoinedToSelf) {
        //this signal is: server --> clients. so send to all clients
        if (mHostChatInterface != null)
          mHostChatInterface.gameCommand(data);
        receivedGameCommand(m_bus_unique_name, data); //send to ourself
      } else {
        if(mChatInterface!=null) mChatInterface.gameCommand(data);
      }
    } catch (BusException ex) {
        alljoynError(Module.USE, AllJoynError.SEND_ERROR, 
            "Bus exception while sending message: (" + ex + ")");
    }
    }
  
    /* receiving messages */
    //will return null if there are no messages left
    public NetworkData receiveSensorUpdate() {
      return m_sensor_updates.poll();
    }
    public NetworkData receiveGameCommand() {
      return m_game_commands.poll();
    }
    //this will return a server_id
    public String receiveServerFound() {
      return m_server_found.poll();
    }
    public String receiveServerLost() {
      return m_server_lost.poll();
    }
    //this is the own unique name
    public String getUniqueName() {
      return m_bus_unique_name;
    }
    
    /* joined clients */
    
  public static class ConnectedClient {
    public String unique_id; //same as packet sender
    public String well_known_name; //can be null, until signals are sent to everyone
      //use getNameFromServerId to get the name from this
    
    public short id = -1; //game id: server decides which client gets which id
  }
  private List<ConnectedClient> m_connected_clients;
  
  public synchronized ConnectedClient connectedClient(int idx) {
    if(idx < m_connected_clients.size())
      return m_connected_clients.get(idx);
    return null;
  }
  public synchronized int connectedClientCount() {
    return m_connected_clients.size();
  }
  
    
    //set this before start advertising
    //use -1 for unlimited
    public void setMaxClientCount(int max_count) {
      m_max_client_count = max_count;
    }
    public int maxClientCount() {
      return m_max_client_count;
    }
    
    
    private volatile int m_max_client_count = -1;
    private volatile boolean m_clients_can_join = false; //clients can only join when advertising
    
  public synchronized void registerEventListener(Handler h) {
    m_event_listeners.add(h);
  }
  public synchronized void unregisterEventListener(Handler h) {
    for(int i=0; i<m_event_listeners.size(); ++i) {
      if(m_event_listeners.get(i) == h) {
        m_event_listeners.remove(i);
        return;
      }
    }
  }
  //event notification messages -> msg.what
    public static final int HANDLE_RECEIVED_SIGNAL = 0;
    public static final int HANDLE_CLIENT_JOINED = 1;
    public static final int HANDLE_CLIENT_LEFT = 2;
    public static final int HANDLE_SERVER_FOUND = 3;
    public static final int HANDLE_SERVER_LOST = 4;
    public static final int HANDLE_ERROR = 5;
    
    private volatile AllJoynErrorData m_error = null;
    
    public AllJoynErrorData getError() {
      return m_error;
    }
    public void resetErrors() {
      m_error = null;
    }
  
    //Note: server_name must NOT contain '.'
    //it can only consist of: [A-Z][a-z][0-9]_-
    public void setServerName(String server_name) {
      m_host_server_name = new String(server_name);
    }
    
  /* advertising */
  //call this to let the others discover me
    //first call setServerName
  public void startAdvertise() {
    m_clients_can_join = true;
    m_background_handler.requestName();
    m_background_handler.bindSession();
    m_background_handler.advertise();
  }
  public void stopAdvertise() {
    m_clients_can_join = false;
    m_background_handler.cancelAdvertise();
    m_background_handler.unbindSession();
    m_background_handler.releaseName();
  }
  public void setClientsCanJoin(boolean can_join) {
    m_clients_can_join = can_join;
  }
  
  //listen for other servers
  public void startDiscovery() {
     m_background_handler.startDiscovery();
  }
  public void stopDiscovery() {
     m_background_handler.cancelDiscovery();
  }
  
  /* join a network */
  //server_id_to_join is one of the returned receiveServerFound() Strings
    //first call setServerName
  public void joinSession(String server_id_to_join) {
    m_server_id_to_join = new String(server_id_to_join);
    m_background_handler.joinSession();
  }
  public void joinSessionToSelf() {
    //join to ourself
    joinSession(getWellKnownName());
  }
  public void leaveSession() {
    m_background_handler.leaveSession();
    //clear the connected client list
    m_connected_clients = new ArrayList<ConnectedClient>();
  }
  
  public static String getNameFromServerId(String server_id) {
    //server id is: NAME_PREFIX.g<guid>.v<protocol version>.n<server_name>
      int lastDot = server_id.lastIndexOf('.');
      if (lastDot < 0 || lastDot+2 > server_id.length()) {
        //this is a format error. we could throw an exception.
        //but we do our best here to avoid errors
        return server_id;
      }
        return server_id.substring(lastDot + 2);
  }
  public static int getProtocolVersionFromServerId(String server_id) {
    int version_idx = server_id.lastIndexOf(".v");
    int name_idx = server_id.lastIndexOf(".n");
      if (version_idx < 0 || version_idx+2 > server_id.length()
          || name_idx < 0) {
        return -1;
      }
      int ret = -1;
      try {
        ret = Integer.parseInt(server_id.substring(version_idx+2, name_idx));
      } catch(NumberFormatException e) {
      }
      return ret;
  }
  public static String toDisplayableName(String server_name) {
    return server_name.replaceAll("_", " ");
  }
  public static String fromDisplayableName(String server_name_displ) {
    return server_name_displ.replaceAll(" ", "_");
  }
  
  //incoming data
  public static class NetworkData {
    public float pos_x;
    public float pos_y;
    public byte[] data;
    public String sender;
    
  }
  private List<Handler> m_event_listeners = new ArrayList<Handler>();
  private Queue<NetworkData> m_sensor_updates = new ConcurrentLinkedQueue<NetworkData>();
  private Queue<NetworkData> m_game_commands = new ConcurrentLinkedQueue<NetworkData>();
  
  private Queue<String> m_server_found = new ConcurrentLinkedQueue<String>();
  private Queue<String> m_server_lost = new ConcurrentLinkedQueue<String>();
  
  //what is one of HANDLE_*
  private synchronized void sendEventToListeners(int what) {
    for(Handler h: m_event_listeners) {
      Message msg = h.obtainMessage(what);
      h.sendMessage(msg);
    }
  }
  
  /* AllJoyn stuff */
  
    /**
     * Enumeration of the states of the AllJoyn bus attachment.  This
     * lets us make a note to ourselves regarding where we are in the process
     * of preparing and tearing down the fundamental connection to the AllJoyn
     * bus.
     * 
     * This should really be a more private think, but for the sample we want
     * to show the user the states we are running through.  Because we are
     * really making a data hiding exception, and because we trust ourselves,
     * we don't go to any effort to prevent the UI from changing our state out
     * from under us.
     * 
     * There are separate variables describing the states of the client
     * ("use") and service ("host") pieces.
     */
    public static enum BusAttachmentState {
      DISCONNECTED,  /** The bus attachment is not connected to the AllJoyn bus */ 
      CONNECTED,    /** The  bus attachment is connected to the AllJoyn bus */
      DISCOVERING    /** The bus attachment is discovering remote attachments hosting chat channels */
    }
    
    /**
     * The state of the AllJoyn bus attachment.
     */
    private BusAttachmentState mBusAttachmentState = BusAttachmentState.DISCONNECTED;
    
    private boolean isBusConnected() {
      return mBusAttachmentState == BusAttachmentState.CONNECTED
          || mBusAttachmentState == BusAttachmentState.DISCOVERING;
    }
    public boolean isDiscovering() {
      return mBusAttachmentState == BusAttachmentState.DISCOVERING;
    }
    
    /**
     * Enumeration of the states of a hosted chat channel.  This lets us make a
     * note to ourselves regarding where we are in the process of preparing
     * and tearing down the AllJoyn pieces responsible for providing the chat
     * service.  In order to be out of the IDLE state, the BusAttachment state
     * must be at least CONNECTED.
     */
    public static enum HostChannelState {
      IDLE,          /** There is no hosted chat channel */ 
      NAMED,        /** The well-known name for the channel has been successfully acquired */
      BOUND,      /** A session port has been bound for the channel */
      ADVERTISED,      /** The bus attachment has advertised itself as hosting an chat channel */
      CONNECTED       /** At least one remote device has connected to a session on the channel */
    }
    
    /**
     * The state of the AllJoyn components responsible for hosting an chat channel.
     */
    private HostChannelState mHostChannelState = HostChannelState.IDLE;
    
    /**
     * Enumeration of the states of a hosted chat channel.  This lets us make a
     * note to ourselves regarding where we are in the process of preparing
     * and tearing down the AllJoyn pieces responsible for providing the chat
     * service.  In order to be out of the IDLE state, the BusAttachment state
     * must be at least CONNECTED.
     */
    public static enum UseChannelState {
      IDLE,          /** There is no used chat channel */ 
      JOINED,        /** The session for the channel has been successfully joined */
    }
    
    /**
     * The state of the AllJoyn components responsible for hosting an chat channel.
     */
    private UseChannelState mUseChannelState = UseChannelState.IDLE;
    
    
    /**
     * This is the AllJoyn background thread handler class.  AllJoyn is a
     * distributed system and must therefore make calls to other devices over
     * networks.  These calls may take arbitrary amounts of time.  The Android
     * application framework is fundamentally single-threaded and so the main
     * Service thread that is executing in our component is the same thread as
     * the ones which appear to be executing the user interface code in the
     * other Activities.  We cannot block this thread while waiting for a
     * network to respond, so we need to run our calls in the context of a
     * background thread.  This is the class that provides that background
     * thread implementation.
     *
     * When we need to do some possibly long-lived task, we just pass a message
     * to an object implementing this class telling it what needs to be done.
     * There are two main parts to this class:  an external API and the actual
     * handler.  In order to make life easier for callers, we provide API
     * methods to deal with the actual message passing, and then when the
     * handler thread is executing the desired method, it calls out to an 
     * implementation in the enclosing class.  For example, in order to perform
     * a connect() operation in the background, the enclosing class calls
     * BackgroundHandler.connect(); and the result is that the enclosing class
     * method doConnect() will be called in the context of the background
     * thread.
     */
    private final class BackgroundHandler extends Handler {
        public BackgroundHandler(Looper looper) {
            super(looper);
        }
        
        /**
         * Exit the background handler thread.  This will be the last message
         * executed by an instance of the handler.
         */
        public void exit() {
            Log.i(TAG, "mBackgroundHandler.exit()");
          Message msg = m_background_handler.obtainMessage(EXIT);
            m_background_handler.sendMessage(msg);
        }
        
        /**
         * Connect the application to the Alljoyn bus attachment.  We expect
         * this method to be called in the context of the main Service thread.
         * All this method does is to dispatch a corresponding method in the
         * context of the service worker thread.
         */
        public void connect() {
            Log.i(TAG, "mBackgroundHandler.connect()");
          Message msg = m_background_handler.obtainMessage(CONNECT);
            m_background_handler.sendMessage(msg);
        }
        
        /**
         * Disonnect the application from the Alljoyn bus attachment.  We
         * expect this method to be called in the context of the main Service
         * thread.  All this method does is to dispatch a corresponding method
         * in the context of the service worker thread.
         */
        public void disconnect() {
            Log.i(TAG, "mBackgroundHandler.disconnect()");
          Message msg = m_background_handler.obtainMessage(DISCONNECT);
            m_background_handler.sendMessage(msg);
        }

        /**
         * Start discovering remote instances of the application.  We expect
         * this method to be called in the context of the main Service thread.
         * All this method does is to dispatch a corresponding method in the
         * context of the service worker thread.
         */
        public void startDiscovery() {
            Log.i(TAG, "mBackgroundHandler.startDiscovery()");
          Message msg = m_background_handler.obtainMessage(START_DISCOVERY);
          m_background_handler.sendMessage(msg);
        }
        
        /**
         * Stop discovering remote instances of the application.  We expect
         * this method to be called in the context of the main Service thread.
         * All this method does is to dispatch a corresponding method in the
         * context of the service worker thread.
         */
        public void cancelDiscovery() {
            Log.i(TAG, "mBackgroundHandler.stopDiscovery()");
          Message msg = m_background_handler.obtainMessage(CANCEL_DISCOVERY);
          m_background_handler.sendMessage(msg);
        }

        public void requestName() {
            Log.i(TAG, "mBackgroundHandler.requestName()");
          Message msg = m_background_handler.obtainMessage(REQUEST_NAME);
          m_background_handler.sendMessage(msg);
        }
        
        public void releaseName() {
            Log.i(TAG, "mBackgroundHandler.releaseName()");
          Message msg = m_background_handler.obtainMessage(RELEASE_NAME);
          m_background_handler.sendMessage(msg);
        }
        
        public void bindSession() {
            Log.i(TAG, "mBackgroundHandler.bindSession()");
          Message msg = m_background_handler.obtainMessage(BIND_SESSION);
          m_background_handler.sendMessage(msg);
        }
        
        public void unbindSession() {
            Log.i(TAG, "mBackgroundHandler.unbindSession()");
          Message msg = m_background_handler.obtainMessage(UNBIND_SESSION);
          m_background_handler.sendMessage(msg);
        }
        
        public void advertise() {
            Log.i(TAG, "mBackgroundHandler.advertise()");
          Message msg = m_background_handler.obtainMessage(ADVERTISE);
          m_background_handler.sendMessage(msg);
        }
        
        public void cancelAdvertise() {
            Log.i(TAG, "mBackgroundHandler.cancelAdvertise()");
          Message msg = m_background_handler.obtainMessage(CANCEL_ADVERTISE);
          m_background_handler.sendMessage(msg);
        }
        
        public void joinSession() {
            Log.i(TAG, "mBackgroundHandler.joinSession()");
          Message msg = m_background_handler.obtainMessage(JOIN_SESSION);
          m_background_handler.sendMessage(msg);
        }
        
        public void leaveSession() {
            Log.i(TAG, "mBackgroundHandler.leaveSession()");
          Message msg = m_background_handler.obtainMessage(LEAVE_SESSION);
          m_background_handler.sendMessage(msg);
        }
                 
        /**
         * The message handler for the worker thread that handles background
         * tasks for the AllJoyn bus.
         */
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case CONNECT:
              doConnect();
              break;
          case DISCONNECT:
            doDisconnect();
          break;
            case START_DISCOVERY:
              doStartDiscovery();
              break;
          case CANCEL_DISCOVERY:
            doStopDiscovery();
          break;
          case REQUEST_NAME:
            doRequestName();
          break;
          case RELEASE_NAME:
            doReleaseName();
          break;    
          case BIND_SESSION:
            doBindSession();
          break;
          case UNBIND_SESSION:
            doUnbindSession();
            break;
          case ADVERTISE:
            doAdvertise();
          break;
          case CANCEL_ADVERTISE:
            doCancelAdvertise();            
          break;  
          case JOIN_SESSION:
            doJoinSession();
          break;
          case LEAVE_SESSION:
            doLeaveSession();
            break;
          case EXIT:
                doExit();
                getLooper().quit();
                break;
        default:
          break;
            }
        }
    }
    
    private static final int EXIT = 1;
    private static final int CONNECT = 2;
    private static final int DISCONNECT = 3;
    private static final int START_DISCOVERY = 4;
    private static final int CANCEL_DISCOVERY = 5;
    private static final int REQUEST_NAME = 6;
    private static final int RELEASE_NAME = 7;
    private static final int BIND_SESSION = 8;
    private static final int UNBIND_SESSION = 9;
    private static final int ADVERTISE = 10;
    private static final int CANCEL_ADVERTISE = 11;
    private static final int JOIN_SESSION = 12;
    private static final int LEAVE_SESSION = 13;
    
    /**
     * The instance of the AllJoyn background thread handler.  It is created
     * when Android decides the Service is needed and is called from the
     * onCreate() method.  When Android decides our Service is no longer 
     * needed, it will call onDestroy(), which spins down the thread.
     */
    private BackgroundHandler m_background_handler = null;
    
    /**
     * Since basically our whole reason for being is to spin up a thread to
     * handle long-lived remote operations, we provide thsi method to do so.
     */
    private void startBusThread() {
      HandlerThread busThread = new HandlerThread("BackgroundHandler");
        busThread.start();
      m_background_handler = new BackgroundHandler(busThread.getLooper());
    }
    
    /**
     * When Android decides that our Service is no longer needed, we need to
     * tear down the thread that is servicing our long-lived remote operations.
   * This method does so. 
     */
    private void stopBusThread() {
        m_background_handler.exit();
        //wait for the background thread to quit
        try {
      m_background_handler.getLooper().getThread().join();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    }
    
    /**
     * The bus attachment is the object that provides AllJoyn services to Java
     * clients.  Pretty much all communiation with AllJoyn is going to go through
     * this obejct.
     */
    private volatile BusAttachment mBus = null;
    private volatile String m_bus_unique_name = null;
    
    /**
     * The well-known name prefix which all bus attachments hosting a channel
     * will use.  The NAME_PREFIX and the channel name are composed to give
     * the well-known name a hosting bus attachment will request and 
     * advertise.
     */
    private static final String NAME_PREFIX = 
        "com.android.game.clash_of_the_balls.alljoyn";
    private volatile String m_host_server_name; //only server name
    private volatile String m_server_id_to_join; //this is the well-known name
    
    private String getWellKnownName() {
      return NAME_PREFIX + ".g" + mBus.getGlobalGUIDString() 
          + ".v" + protocol_version
          + ".n" + m_host_server_name;
    }
    private String getWellKnownNameToJoin() {
      return m_server_id_to_join;
    }
    
  /**
   * The well-known session port used as the contact port for the chat service.
   */
    private static final short CONTACT_PORT = 27;
    
    /**
     * The object path used to identify the service "location" in the bus
     * attachment.
     */
    private static final String OBJECT_PATH = "/gameService";
    
    
    /**
     * The ChatBusListener is a class that listens to the AllJoyn bus for
     * notifications corresponding to the existence of events happening out on
     * the bus.  We provide one implementation of our listener to the bus
     * attachment during the connect(). 
     */
    private class NetworkBusListener extends BusListener {
       /**
     * This method is called when AllJoyn discovers a remote attachment
     * that is hosting an chat channel.  We expect that since we only
     * do a findAdvertisedName looking for instances of the chat
     * well-known name prefix we will only find names that we know to
     * be interesting.  When we find a remote application that is
     * hosting a channel, we add its channel name it to the list of
     * available channels selectable by the user.
         *
         * In the class documentation for the BusListener note that it is a
         * requirement for this method to be multithread safe.  This is
         * accomplished by the use of a monitor on the ChatApplication as
         * exemplified by the synchronized attribute of the addFoundChannel
         * method there.
     */
    public void foundAdvertisedName(String name, short transport, String namePrefix) {
            Log.i(TAG, "mBusListener.foundAdvertisedName(" + name + ")");
            m_server_found.add(name); //name is well known name
            sendEventToListeners(HANDLE_SERVER_FOUND);
    }
    
       /**
     * This method is called when AllJoyn decides that a remote bus
     * attachment that is hosting an chat channel is no longer available.
     * When we lose a remote application that is hosting a channel, we
     * remote its name from the list of available channels selectable
     * by the user.  
         *
         * In the class documentation for the BusListener note that it is a
         * requirement for this method to be multithread safe.  This is
         * accomplished by the use of a monitor on the ChatApplication as
         * exemplified by the synchronized attribute of the removeFoundChannel
         * method there.
     */
    public void lostAdvertisedName(String name, short transport, String namePrefix) {
            Log.i(TAG, "mBusListener.lostAdvertisedName(" + name + ")");
            m_server_lost.add(name); //name is well known name
            sendEventToListeners(HANDLE_SERVER_LOST);
    }
    }
    
    /**
     * An instance of an AllJoyn bus listener that knows what to do with
     * foundAdvertisedName and lostAdvertisedName notifications.  Although
     * we often use the anonymous class idiom when talking to AllJoyn, the
     * bus listener works slightly differently and it is better to use an
     * explicitly declared class in this case.
     */
    private NetworkBusListener mBusListener = new NetworkBusListener();
    
    /**
     * Implementation of the functionality related to connecting our app
     * to the AllJoyn bus.  We expect that this method will only be called in
     * the context of the AllJoyn bus handler thread; and while we are in the
     * DISCONNECTED state.
     */
    private void doConnect() {
        Log.i(TAG, "doConnect()");
        org.alljoyn.bus.alljoyn.DaemonInit.PrepareDaemon(m_context);
      assert(mBusAttachmentState == BusAttachmentState.DISCONNECTED);
      mBus.useOSLogging(true);
      mBus.setDebugLevel("ALLJOYN_JAVA", 5);
      mBus.registerBusListener(mBusListener);
      
        /* 
         * To make a service available to other AllJoyn peers, first
         * register a BusObject with the BusAttachment at a specific
         * object path.  Our service is implemented by the ChatService
         * BusObject found at the "/chatService" object path.
         */
        Status status = mBus.registerBusObject((BusObject)m_network_service, OBJECT_PATH);
        if (Status.OK != status) {
        alljoynError(Module.HOST, AllJoynError.CONNECT_ERROR, 
            "Unable to register the bus object: (" + status + ")");
          return;
        }
      
      status = mBus.connect();
      if (status != Status.OK) {
        alljoynError(Module.GENERAL, AllJoynError.CONNECT_ERROR, 
            "Unable to connect to the bus: (" + status + ")");
          return;
      }
      
        status = mBus.registerSignalHandlers(this);
      if (status != Status.OK) {
        alljoynError(Module.GENERAL, AllJoynError.CONNECT_ERROR, 
            "Unable to register signal handlers: (" + status + ")");
          return;
      }
      
      m_bus_unique_name = mBus.getUniqueName();
      mBusAttachmentState = BusAttachmentState.CONNECTED;
    }  
    
    /**
     * Implementation of the functionality related to disconnecting our app
     * from the AllJoyn bus.  We expect that this method will only be called
     * in the context of the AllJoyn bus handler thread.  We expect that this
     * method will only be called in the context of the AllJoyn bus handler
     * thread; and while we are in the CONNECTED state.
     */
    private boolean doDisconnect() {
        Log.i(TAG, "doDisonnect()");
      if(mBusAttachmentState == BusAttachmentState.CONNECTED) {
        mBus.unregisterBusListener(mBusListener);
        mBus.disconnect();
        mBusAttachmentState = BusAttachmentState.DISCONNECTED;
      }
      return true;
    }
    
    /**
     * Implementation of the functionality related to discovering remote apps
     * which are hosting chat channels.  We expect that this method will only
     * be called in the context of the AllJoyn bus handler thread; and while
     * we are in the CONNECTED state.  Since this is a core bit of functionalty
     * for the "use" side of the app, we always do this at startup.
     */
    private void doStartDiscovery() {
        Log.i(TAG, "doStartDiscovery()");
      assert(mBusAttachmentState == BusAttachmentState.CONNECTED);
        Status status = mBus.findAdvertisedName(NAME_PREFIX);
      if (status == Status.OK) {
          mBusAttachmentState = BusAttachmentState.DISCOVERING;
      } else {
        alljoynError(Module.USE, AllJoynError.START_DISCOVERY_ERROR,
          "Unable to start finding advertised names: (" + status + ")");
      }
    }
    
    /**
     * Implementation of the functionality related to stopping discovery of
     * remote apps which are hosting chat channels.
     */
    private void doStopDiscovery() {
        Log.i(TAG, "doStopDiscovery()");
      assert(mBusAttachmentState == BusAttachmentState.CONNECTED);
        mBus.cancelFindAdvertisedName(NAME_PREFIX);
        mBusAttachmentState = BusAttachmentState.CONNECTED;
    }
       
    /**
     * Implementation of the functionality related to requesting a well-known
     * name from an AllJoyn bus attachment.
     */
    private void doRequestName() {
        Log.i(TAG, "doRequestName()");
      
        /*
         * In order to request a name, the bus attachment must at least be
         * connected.
         */
        int stateRelation = mBusAttachmentState.compareTo(BusAttachmentState.DISCONNECTED);
      assert (stateRelation >= 0);
      if(mHostChannelState == HostChannelState.IDLE) {
        /*
         * We depend on the user interface and model to work together to not
         * get this process started until a valid name is set in the channel name.
         */
        String wellKnownName = getWellKnownName();
        Log.i(TAG, "Well-known name: "+wellKnownName);
          Status status = mBus.requestName(wellKnownName, BusAttachment.ALLJOYN_REQUESTNAME_FLAG_DO_NOT_QUEUE
              | BusAttachment.ALLJOYN_NAME_FLAG_ALLOW_REPLACEMENT
              | BusAttachment.ALLJOYN_REQUESTNAME_FLAG_REPLACE_EXISTING);
          if (status == Status.OK) {
              mHostChannelState = HostChannelState.NAMED;
          } else {
          alljoynError(Module.USE, AllJoynError.CONNECT_ERROR, 
              "Unable to acquire well-known name: (" + status + ")");
          }
      }
    }
    
    /**
     * Implementation of the functionality related to releasing a well-known
     * name from an AllJoyn bus attachment.
     */
    private void doReleaseName() {
        Log.i(TAG, "doReleaseName()");
        
        /*
         * In order to release a name, the bus attachment must at least be
         * connected.
         */
      if(mBusAttachmentState == BusAttachmentState.CONNECTED 
          || mBusAttachmentState == BusAttachmentState.DISCOVERING) {
      
        /*
         * We need to progress monotonically down the hosted channel states
         * for sanity.
         */
        if(mHostChannelState == HostChannelState.NAMED) {
          
          /*
           * We depend on the user interface and model to work together to not
           * change the name out from under us while we are running.
           */
          String wellKnownName = getWellKnownName();
    
          /*
           * There's not a lot we can do if the bus attachment refuses to release
           * the name.  It is not a fatal error, though, if it doesn't.  This is
           * because bus attachments can have multiple names.
           */
          mBus.releaseName(wellKnownName);
          mHostChannelState = HostChannelState.IDLE;
        }
      }
    }
    
    /**
     * Implementation of the functionality related to binding a session port
     * to an AllJoyn bus attachment.
     */
    private void doBindSession() {
        Log.i(TAG, "doBindSession()");
        
        if(mHostChannelState == HostChannelState.IDLE 
            || mHostChannelState == HostChannelState.NAMED) {
          
          Mutable.ShortValue contactPort = new Mutable.ShortValue(CONTACT_PORT);
          SessionOpts sessionOpts = new SessionOpts(SessionOpts.TRAFFIC_MESSAGES
              , true, SessionOpts.PROXIMITY_ANY, SessionOpts.TRANSPORT_ANY);
          
          Status status = mBus.bindSessionPort(contactPort, sessionOpts, new SessionPortListener() {
              /**
               * This method is called when a client tries to join the session
               * we have bound.  It asks us if we want to accept the client into
               * our session.
               *
               * In the class documentation for the SessionPortListener note that
               * it is a requirement for this method to be multithread safe.
               * Since we never access any shared state, this requirement is met.
               */
            public boolean acceptSessionJoiner(short sessionPort, String joiner, SessionOpts sessionOpts) {
                  Log.i(TAG, "SessionPortListener.acceptSessionJoiner(" + sessionPort + ", " + joiner + ", " + sessionOpts.toString() + ")");
            
                  /*
               * Accept anyone who can get our contact port correct.
               */
              if (sessionPort == CONTACT_PORT && m_clients_can_join) {
                
                
                int connected_clients = connectedClientCount();
                
                if(m_max_client_count==-1 || connected_clients < m_max_client_count) {
                  
                  return true;
                  
                }
              }
              return false;
              }
              
              /**
               * If we return true in acceptSessionJoiner, we admit a new client
               * into our session.  The session does not really exist until a 
               * client joins, at which time the session is created and a session
               * ID is assigned.  This method communicates to us that this event
               * has happened, and provides the new session ID for us to use.
               *
               * In the class documentation for the SessionPortListener note that
               * it is a requirement for this method to be multithread safe.
               * Since we never access any shared state, this requirement is met.
               * 
               * See comments in joinSession for why the hosted chat interface is
               * created here. 
               */
              public void sessionJoined(short sessionPort, int id, String joiner) {
                  Log.i(TAG, "SessionPortListener.sessionJoined(" + sessionPort + ", " + id + ", " + joiner + ")");
                  mHostSessionId = id;
                  SignalEmitter emitter = new SignalEmitter(m_network_service, id
                      , SignalEmitter.GlobalBroadcast.Off);
                  mHostChatInterface = emitter.getInterface(AlljoynInterface.class);
              }             
          });
          
          if (status == Status.OK) {
            mHostChannelState = HostChannelState.BOUND;
          } else {
          alljoynError(Module.HOST, AllJoynError.CONNECT_ERROR,
              "Unable to bind session contact port: (" + status + ")");
            return;
          }
      }
    }
    
    /**
     * Implementation of the functionality related to un-binding a session port
     * from an AllJoyn bus attachment.
     */
    private void doUnbindSession() {
        Log.i(TAG, "doUnbindSession()");
        
        /*
         * There's not a lot we can do if the bus attachment refuses to unbind
         * our port.
         */
       mBus.unbindSessionPort(CONTACT_PORT);
        mHostChatInterface = null;
       mHostChannelState = HostChannelState.NAMED;
    }
    
    /**
     * The session identifier of the "host" session that the application
     * provides for remote devices.  Set to -1 if not connected.
     */
    int mHostSessionId = -1;
    
    /**
     * A flag indicating that the application has joined a chat channel that
     * it is hosting.  See the long comment in doJoinSession() for a
     * description of this rather non-intuitively complicated case.
     */
    boolean mJoinedToSelf = false;
    
    /**
     * This is the interface over which the chat messages will be sent in
     * the case where the application is joined to a chat channel hosted
     * by the application.  See the long comment in doJoinSession() for a
     * description of this rather non-intuitively complicated case.
     */
    AlljoynInterface mHostChatInterface = null;
    
    /**
     * Implementation of the functionality related to advertising a service on
     * an AllJoyn bus attachment.
     */
    private void doAdvertise() {
        Log.i(TAG, "doAdvertise()");
        
         /*
       * We depend on the user interface and model to work together to not
       * change the name out from under us while we are running.
       */
      String wellKnownName = getWellKnownName();        
        Status status = mBus.advertiseName(wellKnownName, SessionOpts.TRANSPORT_ANY);
        
        if (status == Status.OK) {
          mHostChannelState = HostChannelState.ADVERTISED;
        } else {
        alljoynError(Module.HOST, AllJoynError.ADVERTISE_ERROR,
            "Unable to advertise well-known name: (" + status + ")");
        }
    }
    
    /**
     * Implementation of the functionality related to canceling an advertisement
     * on an AllJoyn bus attachment.
     */
    private void doCancelAdvertise() {
        Log.i(TAG, "doCancelAdvertise()");
        
         /*
       * We depend on the user interface and model to work together to not
       * change the name out from under us while we are running.
       */
      String wellKnownName = getWellKnownName();        
        Status status = mBus.cancelAdvertiseName(wellKnownName, SessionOpts.TRANSPORT_ANY);
        
        if (status != Status.OK) {
        alljoynError(Module.HOST, AllJoynError.ADVERTISE_CANCEL_ERROR,
            "Unable to cancel advertisement of well-known name: (" + status + ")");
          return;
        }
        
        /*
         * There's not a lot we can do if the bus attachment refuses to cancel
         * our advertisement, so we don't bother to even get the status.
         */
       mHostChannelState = HostChannelState.BOUND;
    }
    
    /**
     * Implementation of the functionality related to joining an existing
     * local or remote session.
     */
    private void doJoinSession() {
        Log.i(TAG, "doJoinSession()");
        
        /*
         * There is a relatively non-intuitive behavior of multipoint sessions
         * that one needs to grok in order to understand the code below.  The
         * important thing to uderstand is that there can be only one endpoint
         * for a multipoint session in a particular bus attachment.  This
         * endpoint can be created explicitly by a call to joinSession() or
         * implicitly by a call to bindSessionPort().  An attempt to call
         * joinSession() on a session port we have created with bindSessionPort()
         * will result in an error.
         * 
         * When we call bindSessionPort(), we do an implicit joinSession() and
         * thus signals (which correspond to our chat messages) will begin to
         * flow from the hosted chat channel as soon as we begin to host a
         * corresponding session.
         * 
         * To achieve sane user interface behavior, we need to block those
         * signals from the implicit join done by the bind until our user joins
         * the bound chat channel.  If we do not do this, the chat messages
         * from the chat channel hosted by the application will appear in the
         * chat channel joined by the application.
         *
         * Since the messages flow automatically, we can accomplish this by
         * turning a filter on and off in the chat signal handler.  So if we
         * detect that we are hosting a channel, and we find that we want to
         * join the hosted channel we turn the filter off.
         * 
         * We also need to be able to send chat messages to the hosted channel.
         * This means we need to point the mChatInterface at the session ID of
         * the hosted session.  There is another complexity here since the
         * hosted session doesn't exist until a remote session has joined.
         * This means that we don't have a session ID to use to create a
         * SignalEmitter until a remote device does a joinSession on our
         * hosted session.  This, in turn, means that we have to create the
         * SignalEmitter after we get a sessionJoined() callback in the 
         * SessionPortListener passed into bindSessionPort().  We chose to
         * create the signal emitter for this case in the sessionJoined()
         * callback itself.  Note that this hosted channel signal emitter
         * must be distinct from one constructed for the usual joinSession
         * since a hosted channel may have a remote device do a join at any
         * time, even when we are joined to another session.  If they were
         * not separated, a remote join on the hosted session could redirect
         * messages from the joined session unexpectedly.
         * 
         * So, to summarize, these next few lines handle a relatively complex
         * case.  When we host a chat channel, we do a bindSessionPort which
         * *enables* the creation of a session.  As soon as a remote device
         * joins the hosted chat channel, a session is actually created, and
         * the SessionPortListener sessionJoined() callback is fired.  At that
         * point, we create a separate SignalEmitter using the hosted session's
         * sessionId that we can use to send chat messages to the channel we
         * are hosting.  As soon as the session comes up, we begin receiving
         * chat messages from the session, so we need to filter them until the
         * user joins the hosted chat channel.  In a separate timeline, the
         * user can decide to join the chat channel she is hosting.  She can
         * do so either before or after the corresponding session has been
         * created as a result of a remote device joining the hosted session. 
         * If she joins the hosted channel before the underlying session is
         * created, her chat messages will be discarded.  If she does so after
         * the underlying session is created, there will be a session emitter
         * waiting to use to send chat messages.  In either case, the signal
         * filter will be turned off in order to listen to remote chat
         * messages.
         */
        
         /*
       * We depend on the user interface and model to work together to provide
       * a reasonable name.
       */
      final String wellKnownNameToJoin = getWellKnownNameToJoin();
      
        if (mHostChannelState != HostChannelState.IDLE) {
          if (wellKnownNameToJoin.equals(getWellKnownName())) {              
               mUseChannelState = UseChannelState.JOINED;
            mJoinedToSelf = true;
            handleClientJoined(getUniqueName(), getWellKnownName());
            Log.d(TAG, "JoinSession: we are joined to ourself");
                return;
          }
        }
        
        /*
         * Since we can act as the host of a channel, we know what the other
         * side is expecting to see.
         */
      short contactPort = CONTACT_PORT;
        SessionOpts sessionOpts = new SessionOpts(SessionOpts.TRAFFIC_MESSAGES
            , true, SessionOpts.PROXIMITY_ANY, SessionOpts.TRANSPORT_ANY);
        Mutable.IntegerValue sessionId = new Mutable.IntegerValue();
        
        Status status = mBus.joinSession(wellKnownNameToJoin, contactPort, sessionId
            , sessionOpts, new SessionListener() {
            /**
             * This method is called when the last remote participant in the 
             * chat session leaves for some reason and we no longer have anyone
             * to chat with.
             *
             * In the class documentation for the BusListener note that it is a
             * requirement for this method to be multithread safe.  This is
             * accomplished by the use of a monitor on the ChatApplication as
             * exemplified by the synchronized attribute of the removeFoundChannel
             * method there.
             */
            public void sessionLost(int sessionId) {
                Log.i(TAG, "BusListener.sessionLost(" + sessionId + ")");
            alljoynError(Module.USE, AllJoynError.JOIN_SESSION_ERROR, 
                "The session has been lost");
               mUseChannelState = UseChannelState.IDLE;
            }
            
            public void sessionMemberAdded(int sessionId, String uniqueName) {
              handleClientJoined(uniqueName, null);
            }
            
            public void sessionMemberRemoved(int sessionId, String uniqueName) {
              handleClientLeft(uniqueName);
            }
        });
        
        if (status == Status.OK) {
            Log.i(TAG, "doJoinSession(): use sessionId is " + mUseSessionId);
          mUseSessionId = sessionId.value;
        } else {
        alljoynError(Module.USE, AllJoynError.JOIN_SESSION_ERROR, 
            "Unable to join session: (" + status + ")");
          return;
        }
        
        SignalEmitter emitter = new SignalEmitter(m_network_service, wellKnownNameToJoin, 
            mUseSessionId, SignalEmitter.GlobalBroadcast.Off);
        mChatInterface = emitter.getInterface(AlljoynInterface.class);
        
        //now that we joined the session we must let the server know which 
        //well-known name we have
        mChatInterface.clientInfoToServer(getWellKnownName());
        
       mUseChannelState = UseChannelState.JOINED;
    }
    
    /**
     * This is the interface over which the chat messages will be sent.
     */
    AlljoynInterface mChatInterface = null;
    
    /**
     * Implementation of the functionality related to joining an existing
     * remote session.
     */
    private void doLeaveSession() {
        Log.i(TAG, "doLeaveSession()");
        if (mJoinedToSelf == false) {
          mBus.leaveSession(mUseSessionId);
        } else {
          handleClientLeft(getUniqueName());
        }
        mUseSessionId = -1;
        mJoinedToSelf = false;
        mChatInterface = null;
       mUseChannelState = UseChannelState.IDLE;
    }
    
    private void doExit() {
      Log.i(TAG, "doExit()");
      mBus.unregisterBusObject((BusObject)m_network_service);
      mBus=null;
    }
    
    private synchronized void handleClientJoined(String unique_name
        , String well_known_name) {
      if(unique_name != null) {
        Log.i(TAG, "Client joined: "+unique_name);

        //check if already added
        boolean exists=false;
        for(ConnectedClient client : m_connected_clients) {
          if(client.unique_id.equals(unique_name)) {
            exists=true;
            if(well_known_name != null && client.well_known_name==null)
              client.well_known_name = well_known_name;
          }
        }
        if(!exists) {
          ConnectedClient c=new ConnectedClient();
          c.well_known_name = well_known_name;
          c.unique_id = unique_name;
          m_connected_clients.add(c);
          
          sendEventToListeners(HANDLE_CLIENT_JOINED);
        }
        
      } else {
        Log.e(TAG, "handleClientJoined: unique_name is NULL!");
      }
    }
    private synchronized void handleClientLeft(String unique_name) {
      if(unique_name != null) {
        Log.i(TAG, "Client left: "+unique_name);

      for(int i=0; i<m_connected_clients.size(); ++i) {
        if(m_connected_clients.get(i).unique_id.equals(unique_name)) {
          m_connected_clients.remove(i);
        }
      }

        sendEventToListeners(HANDLE_CLIENT_LEFT);
      } else {
        Log.e(TAG, "handleClientLeft: unique_name is NULL!");
      }
    }
    
    /**
     * The session identifier of the "use" session that the application
     * uses to talk to remote instances.  Set to -1 if not connectecd.
     */
    int mUseSessionId = -1;
    

    /**
     * Our chat messages are going to be Bus Signals multicast out onto an 
     * associated session.  In order to send signals, we need to define an
     * AllJoyn bus object that will allow us to instantiate a signal emmiter.
     */
    class NetworkService implements AlljoynInterface, BusObject {
      /**                                                                                                                          
         * Intentionally empty implementation of Chat method.  Since this
         * method is only used as a signal emitter, it will never be called
         * directly.
       */
    @BusSignal
    public void sensorUpdate(double pos_x, double pos_y)
        throws BusException { }
    
    @BusSignal
    public void gameCommand(byte[] data) throws BusException { }

    @BusSignal
    public void clientInfoToServer(String well_known_name) { }

    @BusSignal
    public void clientInfoToClients(String unique_name,
        String well_known_name) { }     
    }

    /**
     * The ChatService is the instance of an AllJoyn interface that is exported
     * on the bus and allows us to send signals implementing messages
     */
    private NetworkService m_network_service;

    /**
     * The signal handler for messages received from the AllJoyn bus.
     * 
     * Since the messages sent on a chat channel will be sent using a bus
     * signal, we need to provide a signal handler to receive those signals.
     * This is it.  Note that the name of the signal handler has the first
     * letter capitalized to conform with the DBus convention for signal 
     * handler names.
     */
    @BusSignalHandler(iface = "com.android.game.clash_of_the_balls.alljoyn", signal = "sensorUpdate")
    public void sensorUpdate(double pos_x, double pos_y) {
      
        /*
       * The only time we allow a signal from the hosted session ID to pass
       * through is if we are in mJoinedToSelf state.  If the source of the
       * signal is us, we also filter out the signal since we are going to
       * locally echo the signal.
        */
      String uniqueName = m_bus_unique_name;
      MessageContext ctx = mBus.getMessageContext();
        
         // Always drop our own signals which may be echoed back from the system.
        if (ctx.sender.equals(uniqueName)) {
            Log.i(TAG, "Chat(): dropped our own signal received on session " + ctx.sessionId);
        return;
      }
        
        receivedSensorUpdate(ctx.sender, pos_x, pos_y);
    }
    private void receivedSensorUpdate(String sender, double pos_x, double pos_y) {
        NetworkData data = new NetworkData();
        data.pos_x = (float)pos_x;
        data.pos_y = (float)pos_y;
        data.sender = sender;
        m_sensor_updates.add(data);
        sendEventToListeners(HANDLE_RECEIVED_SIGNAL);
    }
    @BusSignalHandler(iface = "com.android.game.clash_of_the_balls.alljoyn", signal = "gameCommand")
    public void gameCommand(byte[] data) {
      
        /*
       * The only time we allow a signal from the hosted session ID to pass
       * through is if we are in mJoinedToSelf state.  If the source of the
       * signal is us, we also filter out the signal since we are going to
       * locally echo the signal.
        */
      String uniqueName = m_bus_unique_name;
      MessageContext ctx = mBus.getMessageContext();
        
         // Always drop our own signals which may be echoed back from the system.
        if (ctx.sender.equals(uniqueName)) {
            Log.i(TAG, "Chat(): dropped our own signal received on session " + ctx.sessionId);
        return;
      }

         // Drop signals on the hosted session unless we are joined-to-self.
        if (mJoinedToSelf == false && ctx.sessionId == mHostSessionId) {
            Log.i(TAG, "Chat(): dropped signal received on hosted session " + ctx.sessionId + " when not joined-to-self");
        return;
      }
        
        receivedGameCommand(ctx.sender, data);
    }
    private void receivedGameCommand(String sender, byte[] game_data) {
        NetworkData data = new NetworkData();
        data.data = game_data;
        data.sender = sender;
        m_game_commands.add(data);
        sendEventToListeners(HANDLE_RECEIVED_SIGNAL);
    }
    
    @BusSignalHandler(iface = "com.android.game.clash_of_the_balls.alljoyn", signal = "clientInfoToServer")
  public void clientInfoToServer(String well_known_name) {
      
      String uniqueName = m_bus_unique_name;
      MessageContext ctx = mBus.getMessageContext();
        
         // Always drop our own signals which may be echoed back from the system.
        if (ctx.sender.equals(uniqueName)) {
            Log.i(TAG, "Chat(): dropped our own signal received on session " + ctx.sessionId);
        return;
      }
        
        Log.i(TAG, "got client info: unique name="+ctx.sender
            +", well-known name="+well_known_name);
        
        handleClientJoined(ctx.sender, well_known_name);
        // send update to all clients
        synchronized (this) {
          if (mHostChatInterface != null) {
            for(int i=0; i<m_connected_clients.size(); ++i) {
              ConnectedClient c = m_connected_clients.get(i);
              if(c.unique_id!=null && c.well_known_name!=null)
                mHostChatInterface.clientInfoToClients(c.unique_id, c.well_known_name);
            }
          }
    }
    }

    @BusSignalHandler(iface = "com.android.game.clash_of_the_balls.alljoyn", signal = "clientInfoToClients")
  public void clientInfoToClients(String unique_name,
      String well_known_name) {
      
      String uniqueName = m_bus_unique_name;
      MessageContext ctx = mBus.getMessageContext();
        
         // Always drop our own signals which may be echoed back from the system.
        if (ctx.sender.equals(uniqueName)) {
            Log.i(TAG, "Chat(): dropped our own signal received on session " + ctx.sessionId);
        return;
      }
         // Drop signals on the hosted session unless we are joined-to-self.
        if (mJoinedToSelf == false && ctx.sessionId == mHostSessionId) {
            Log.i(TAG, "Chat(): dropped signal received on hosted session " + ctx.sessionId + " when not joined-to-self");
        return;
      }
        
        Log.i(TAG, "got info from server: unique name="+unique_name
            +", well-known name="+well_known_name);
        
        handleClientJoined(unique_name, well_known_name);
    }   
    
    
    /* error handling */
  /**
   * Enumeration of the high-level moudules in the system.  There is one
   * value per module.
   */
  public static enum Module {
    NONE,
    GENERAL,
    USE,
    HOST
  }
  public static enum AllJoynError {
    CONNECT_ERROR,
    START_DISCOVERY_ERROR,
    ADVERTISE_ERROR,
    ADVERTISE_CANCEL_ERROR,
    JOIN_SESSION_ERROR,
    SEND_ERROR,
    BUS_EXCEPTION,
    RECEIVE_TIMEOUT
  }
  public static String getErrorMsgMultiline(AllJoynError error) {
    switch(error) {
    case ADVERTISE_CANCEL_ERROR: return "Failed to stop\n"+
        "advertisement of \n"+
        "server name";
    case ADVERTISE_ERROR: return "Failed to start\n"+
        "advertisement of \n"+
        "server name";
    case BUS_EXCEPTION: return "Networking bus exception.\n"+
        "cannot send or receive data";
    case CONNECT_ERROR: return "Network: failed to connect";
    case JOIN_SESSION_ERROR: return "Networking session error";
    case SEND_ERROR: return "Failed to send data\n"+
        "over the network";
    case START_DISCOVERY_ERROR: return "Network error happened\n"+
        "when trying to look\n"+
        "for other servers";
    case RECEIVE_TIMEOUT: return "Network receive timeout";
    }
    return "Unknown network error";
  }
  public static class AllJoynErrorData {
    public Module module;
    public AllJoynError error;
    public String error_string;
  }
  
  private void alljoynError(Module m, AllJoynError e, String s) {
    Log.e("AllJoyn", s);
    AllJoynErrorData error = new AllJoynErrorData();
    error.module = m;
    error.error = e;
    error.error_string = s;
    m_error = error;
    
    sendEventToListeners(HANDLE_ERROR);
  }
    
    /*
     * Load the native alljoyn_java library.  The actual AllJoyn code is
     * written in C++ and the alljoyn_java library provides the language
     * bindings from Java to C++ and vice versa.
     */
    static {
        Log.i(TAG, "System.loadLibrary(\"alljoyn_java\")");
        System.loadLibrary("alljoyn_java");
    }
    
    
}




Java Source Code List

au.com.bytecode.opencsv.CSVParser.java
au.com.bytecode.opencsv.CSVReader.java
au.com.bytecode.opencsv.CSVWriter.java
au.com.bytecode.opencsv.ResultSetHelperService.java
au.com.bytecode.opencsv.ResultSetHelper.java
com.sapos_aplastados.game.clash_of_balls.FPSCounter.java
com.sapos_aplastados.game.clash_of_balls.Font2D.java
com.sapos_aplastados.game.clash_of_balls.FontNumbers.java
com.sapos_aplastados.game.clash_of_balls.GameLevel.java
com.sapos_aplastados.game.clash_of_balls.GameRenderer.java
com.sapos_aplastados.game.clash_of_balls.GameSettings.java
com.sapos_aplastados.game.clash_of_balls.ITouchInput.java
com.sapos_aplastados.game.clash_of_balls.LevelManager.java
com.sapos_aplastados.game.clash_of_balls.MainActivity.java
com.sapos_aplastados.game.clash_of_balls.Maths.java
com.sapos_aplastados.game.clash_of_balls.NetworkService.java
com.sapos_aplastados.game.clash_of_balls.ShaderManager.java
com.sapos_aplastados.game.clash_of_balls.TextureBase.java
com.sapos_aplastados.game.clash_of_balls.TextureManager.java
com.sapos_aplastados.game.clash_of_balls.Texture.java
com.sapos_aplastados.game.clash_of_balls.UIBase.java
com.sapos_aplastados.game.clash_of_balls.UIHandler.java
com.sapos_aplastados.game.clash_of_balls.VertexBufferFloat.java
com.sapos_aplastados.game.clash_of_balls.game.DynamicGameObject.java
com.sapos_aplastados.game.clash_of_balls.game.GameBase.java
com.sapos_aplastados.game.clash_of_balls.game.GameField.java
com.sapos_aplastados.game.clash_of_balls.game.GameHole.java
com.sapos_aplastados.game.clash_of_balls.game.GameItem.java
com.sapos_aplastados.game.clash_of_balls.game.GameMenuInGame.java
com.sapos_aplastados.game.clash_of_balls.game.GameObject.java
com.sapos_aplastados.game.clash_of_balls.game.GamePlayer.java
com.sapos_aplastados.game.clash_of_balls.game.GameServer.java
com.sapos_aplastados.game.clash_of_balls.game.GameStatistics.java
com.sapos_aplastados.game.clash_of_balls.game.GameView.java
com.sapos_aplastados.game.clash_of_balls.game.GameWall.java
com.sapos_aplastados.game.clash_of_balls.game.Game.java
com.sapos_aplastados.game.clash_of_balls.game.IDrawable.java
com.sapos_aplastados.game.clash_of_balls.game.IMoveable.java
com.sapos_aplastados.game.clash_of_balls.game.RenderHelper.java
com.sapos_aplastados.game.clash_of_balls.game.SensorThread.java
com.sapos_aplastados.game.clash_of_balls.game.StaticGameObjectNoInteraction.java
com.sapos_aplastados.game.clash_of_balls.game.StaticGameObject.java
com.sapos_aplastados.game.clash_of_balls.game.Vector3D.java
com.sapos_aplastados.game.clash_of_balls.game.Vector.java
com.sapos_aplastados.game.clash_of_balls.game.event.EventGameEnd.java
com.sapos_aplastados.game.clash_of_balls.game.event.EventGameInfo.java
com.sapos_aplastados.game.clash_of_balls.game.event.EventGameStartNow.java
com.sapos_aplastados.game.clash_of_balls.game.event.EventImpact.java
com.sapos_aplastados.game.clash_of_balls.game.event.EventItemAdded.java
com.sapos_aplastados.game.clash_of_balls.game.event.EventItemRemoved.java
com.sapos_aplastados.game.clash_of_balls.game.event.EventItemUpdate.java
com.sapos_aplastados.game.clash_of_balls.game.event.EventPool.java
com.sapos_aplastados.game.clash_of_balls.game.event.Event.java
com.sapos_aplastados.game.clash_of_balls.helper.RawResourceReader.java
com.sapos_aplastados.game.clash_of_balls.helper.ShaderHelper.java
com.sapos_aplastados.game.clash_of_balls.helper.TextureHelper.java
com.sapos_aplastados.game.clash_of_balls.menu.CreationMenu.java
com.sapos_aplastados.game.clash_of_balls.menu.GameMenuBase.java
com.sapos_aplastados.game.clash_of_balls.menu.HelpMenu.java
com.sapos_aplastados.game.clash_of_balls.menu.JoinMenu.java
com.sapos_aplastados.game.clash_of_balls.menu.MainMenu.java
com.sapos_aplastados.game.clash_of_balls.menu.MenuBackground.java
com.sapos_aplastados.game.clash_of_balls.menu.MenuItemArrow.java
com.sapos_aplastados.game.clash_of_balls.menu.MenuItemButton.java
com.sapos_aplastados.game.clash_of_balls.menu.MenuItemGreyButton.java
com.sapos_aplastados.game.clash_of_balls.menu.MenuItemImg.java
com.sapos_aplastados.game.clash_of_balls.menu.MenuItemKeyboard.java
com.sapos_aplastados.game.clash_of_balls.menu.MenuItemLevel.java
com.sapos_aplastados.game.clash_of_balls.menu.MenuItemList.java
com.sapos_aplastados.game.clash_of_balls.menu.MenuItemResultEntry.java
com.sapos_aplastados.game.clash_of_balls.menu.MenuItemStringMultiline.java
com.sapos_aplastados.game.clash_of_balls.menu.MenuItemString.java
com.sapos_aplastados.game.clash_of_balls.menu.MenuItem.java
com.sapos_aplastados.game.clash_of_balls.menu.PopupBase.java
com.sapos_aplastados.game.clash_of_balls.menu.PopupCredit.java
com.sapos_aplastados.game.clash_of_balls.menu.PopupGameStart.java
com.sapos_aplastados.game.clash_of_balls.menu.PopupMsg.java
com.sapos_aplastados.game.clash_of_balls.menu.ResultsMenu.java
com.sapos_aplastados.game.clash_of_balls.menu.WaitMenu.java
com.sapos_aplastados.game.clash_of_balls.network.AlljoynInterface.java
com.sapos_aplastados.game.clash_of_balls.network.NetworkClient.java
com.sapos_aplastados.game.clash_of_balls.network.NetworkServer.java
com.sapos_aplastados.game.clash_of_balls.network.Networking.java