diff options
author | Artur Dryomov <artur.dryomov@gmail.com> | 2013-06-20 18:23:40 +0300 |
---|---|---|
committer | Michael Meeks <michael.meeks@suse.com> | 2013-07-25 18:01:47 +0100 |
commit | d170ecde6ce91f6be43fe465889de4fa4498d25f (patch) | |
tree | 0df652beca8b86f37ba2f43db5188ad5553e6d2f | |
parent | 19015bd364731a30dccea61d1dfddf096b1a6665 (diff) |
Refactor finders classes.
Change-Id: Icaf80e1ff13bca059f6ee42a56f36a4b3f65a3fb
5 files changed, 271 insertions, 195 deletions
diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/BluetoothFinder.java b/android/sdremote/src/org/libreoffice/impressremote/communication/BluetoothFinder.java index 972a8a403074..4ed99a13aa8f 100644 --- a/android/sdremote/src/org/libreoffice/impressremote/communication/BluetoothFinder.java +++ b/android/sdremote/src/org/libreoffice/impressremote/communication/BluetoothFinder.java @@ -10,9 +10,7 @@ package org.libreoffice.impressremote.communication; import java.util.Collection; import java.util.HashMap; - -import org.libreoffice.impressremote.Globals; -import org.libreoffice.impressremote.communication.Server.Protocol; +import java.util.Map; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -22,93 +20,126 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.Handler; import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; -public class BluetoothFinder { +import org.libreoffice.impressremote.communication.Server.Protocol; +public class BluetoothFinder extends BroadcastReceiver { // TODO: add removal of cached items - private Context mContext; + private final Context mContext; - BluetoothAdapter mAdapter; + private final Map<String, Server> mServers; public BluetoothFinder(Context aContext) { mContext = aContext; - mAdapter = BluetoothAdapter.getDefaultAdapter(); + + mServers = new HashMap<String, Server>(); } - public void startFinding() { - Log.i(Globals.TAG, "BluetoothFinder.startFinding(): mAdapter=" + mAdapter); - if (mAdapter == null) { - return; // No bluetooth adapter found (emulator, special devices) + public void startSearch() { + if (!isBluetoothAvailable()) { + return; } - IntentFilter aFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND); - aFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); - aFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - mContext.registerReceiver(mReceiver, aFilter); - mAdapter.startDiscovery(); + + BluetoothAdapter.getDefaultAdapter().startDiscovery(); + + registerSearchResultsReceiver(); } - public void stopFinding() { - Log.i(Globals.TAG, "BluetoothFinder.stopFinding(): mAdapter=" + mAdapter); - if (mAdapter == null) { - return; // No bluetooth adapter found (emulator, special devices) - } - mAdapter.cancelDiscovery(); - try { - mContext.unregisterReceiver(mReceiver); - } catch (IllegalArgumentException e) { - // The receiver wasn't registered - Log.i(Globals.TAG, "BluetoothFinder.stopFinding: " + e); + private boolean isBluetoothAvailable() { + return BluetoothAdapter.getDefaultAdapter() != null; + } + + private void registerSearchResultsReceiver() { + IntentFilter aIntentFilter = new IntentFilter( + BluetoothDevice.ACTION_FOUND); + aIntentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); + aIntentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); + + mContext.registerReceiver(this, aIntentFilter); + } + + public void stopSearch() { + if (!isBluetoothAvailable()) { + return; } + + BluetoothAdapter.getDefaultAdapter().cancelDiscovery(); + + unregisterSearchResultsReceiver(); } - private HashMap<String, Server> mServerList = new HashMap<String, Server>(); + private void unregisterSearchResultsReceiver() { + mContext.unregisterReceiver(this); + } - public Collection<Server> getServerList() { - return mServerList.values(); + public Collection<Server> getServers() { + return mServers.values(); } - private BroadcastReceiver mReceiver = new BroadcastReceiver() { - - @Override - public void onReceive(Context context, Intent aIntent) { - Log.i(Globals.TAG, "BluetoothFinder: BroadcastReceiver.onReceive: aIntent=" + aIntent); - if (aIntent.getAction().equals(BluetoothDevice.ACTION_FOUND)) { - BluetoothDevice aDevice = (BluetoothDevice) aIntent.getExtras() - .get(BluetoothDevice.EXTRA_DEVICE); - Log.i(Globals.TAG, "BluetoothFinder.onReceive: found " + aDevice.getName() + " at " + aDevice.getAddress()); - if (aDevice.getName() == null) - return; - Server aServer = new Server(Protocol.BLUETOOTH, - aDevice.getAddress(), aDevice.getName(), - System.currentTimeMillis()); - mServerList.put(aServer.getAddress(), aServer); - Intent aNIntent = new Intent( - CommunicationService.MSG_SERVERLIST_CHANGED); - LocalBroadcastManager.getInstance(mContext).sendBroadcast( - aNIntent); - } else if (aIntent.getAction().equals( - BluetoothAdapter.ACTION_DISCOVERY_FINISHED) - || aIntent.getAction() - .equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - // Start discovery again after a small delay. - // but check whether device is on incase the user manually - // disabled bluetooth - if (mAdapter.isEnabled()) { - Handler aHandler = new Handler(); - aHandler.postDelayed(new Runnable() { - @Override - public void run() { - // Looping, huh? - Log.i(Globals.TAG, "BluetothFinder: looping"); - } - }, 1000 * 15); - } + @Override + public void onReceive(Context aContext, Intent aIntent) { + if (aIntent.getAction().equals(BluetoothDevice.ACTION_FOUND)) { + BluetoothDevice aBluetoothDevice = (BluetoothDevice) aIntent + .getExtras().get(BluetoothDevice.EXTRA_DEVICE); + + if (aBluetoothDevice == null) { + return; } + createServer(aBluetoothDevice); + + callUpdatingServersList(); + + return; } - }; + if (aIntent.getAction() + .equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) { + startDiscoveryDelayed(); + + return; + } + + if (aIntent.getAction() + .equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) { + startDiscoveryDelayed(); + } + } + + private void createServer(BluetoothDevice aBluetoothDevice) { + String aServerAddress = aBluetoothDevice.getAddress(); + String aServerName = aBluetoothDevice.getName(); + + Server aServer = new Server(Protocol.BLUETOOTH, aServerAddress, + aServerName, System.currentTimeMillis()); + mServers.put(aServerAddress, aServer); + } + + private void callUpdatingServersList() { + Intent aServersListChangedIntent = new Intent( + CommunicationService.MSG_SERVERLIST_CHANGED); + + LocalBroadcastManager.getInstance(mContext) + .sendBroadcast(aServersListChangedIntent); + } + + private void startDiscoveryDelayed() { + // Start discovery again after a small delay. + // but check whether device is on in case the user manually + // disabled bluetooth + + if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) { + return; + } + + Handler aHandler = new Handler(); + aHandler.postDelayed(new Runnable() { + @Override + public void run() { + // Looping, huh? + } + }, 1000 * 15); + } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java index f7401fbde351..00a903940d55 100644 --- a/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java +++ b/android/sdremote/src/org/libreoffice/impressremote/communication/CommunicationService.java @@ -24,6 +24,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Binder; +import android.os.Build; import android.os.IBinder; import android.util.Log; import android.preference.PreferenceManager; @@ -31,7 +32,7 @@ import android.support.v4.content.LocalBroadcastManager; public class CommunicationService extends Service implements Runnable { - public enum State { + public static enum State { DISCONNECTED, SEARCHING, CONNECTING, CONNECTED } @@ -48,7 +49,7 @@ public class CommunicationService extends Service implements Runnable { if (aName != null) return aName; } - return android.os.Build.MODEL; + return Build.MODEL; } /** @@ -139,20 +140,20 @@ public class CommunicationService extends Service implements Runnable { SharedPreferences aPref = PreferenceManager.getDefaultSharedPreferences(this); boolean bEnableWifi = aPref.getBoolean("option_enablewifi", false); if (bEnableWifi) - mNetworkFinder.startFinding(); + mNetworkFinder.startSearch(); BluetoothAdapter aAdapter = BluetoothAdapter.getDefaultAdapter(); if (aAdapter != null) { mBluetoothPreviouslyEnabled = aAdapter.isEnabled(); if (!mBluetoothPreviouslyEnabled) aAdapter.enable(); - mBluetoothFinder.startFinding(); + mBluetoothFinder.startSearch(); } } public void stopSearching() { Log.i(Globals.TAG, "CommunicationService.stopSearching()"); - mNetworkFinder.stopFinding(); - mBluetoothFinder.stopFinding(); + mNetworkFinder.stopSearch(); + mBluetoothFinder.stopSearch(); BluetoothAdapter aAdapter = BluetoothAdapter.getDefaultAdapter(); if (aAdapter != null) { if (!mBluetoothPreviouslyEnabled) { @@ -165,8 +166,8 @@ public class CommunicationService extends Service implements Runnable { Log.i(Globals.TAG, "CommunicationService.connectTo(" + aServer + ")"); synchronized (mConnectionVariableMutex) { if (mState == State.SEARCHING) { - mNetworkFinder.stopFinding(); - mBluetoothFinder.stopFinding(); + mNetworkFinder.stopSearch(); + mBluetoothFinder.stopSearch(); mState = State.DISCONNECTED; } mServerDesired = aServer; @@ -267,8 +268,8 @@ public class CommunicationService extends Service implements Runnable { public List<Server> getServers() { ArrayList<Server> aServers = new ArrayList<Server>(); - aServers.addAll(mNetworkFinder.getServerList()); - aServers.addAll(mBluetoothFinder.getServerList()); + aServers.addAll(mNetworkFinder.getServers()); + aServers.addAll(mBluetoothFinder.getServers()); aServers.addAll(mManualServers.values()); return aServers; } @@ -324,7 +325,6 @@ public class CommunicationService extends Service implements Runnable { } public void removeServer(Server aServer) { - mManualServers.remove(aServer.getAddress()); SharedPreferences aPref = getSharedPreferences(SERVERSTORAGE_KEY, diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/NetworkClient.java b/android/sdremote/src/org/libreoffice/impressremote/communication/NetworkClient.java index abaaf58f3e9d..438148034d0f 100644 --- a/android/sdremote/src/org/libreoffice/impressremote/communication/NetworkClient.java +++ b/android/sdremote/src/org/libreoffice/impressremote/communication/NetworkClient.java @@ -80,7 +80,7 @@ public class NetworkClient extends Client { String aPhoneName = CommunicationService.getDeviceName(); sendCommand(Protocol.Commands - .prepareCommand(Protocol.Commands.PAIR, aPhoneName, mPin)); + .prepareCommand(Protocol.Commands.PAIR_WITH_SERVER, aPhoneName, mPin)); } @Override diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/Protocol.java b/android/sdremote/src/org/libreoffice/impressremote/communication/Protocol.java index 11cf86ef268b..6081669b89c8 100644 --- a/android/sdremote/src/org/libreoffice/impressremote/communication/Protocol.java +++ b/android/sdremote/src/org/libreoffice/impressremote/communication/Protocol.java @@ -22,9 +22,18 @@ final class Protocol { private Ports() { } + public static final int SERVER_SEARCH = 1598; public static final int CLIENT_CONNECTION = 1599; } + public static final class Addresses { + private Addresses() { + } + + public static final String SERVER_SEARCH = "239.0.0.1"; + public static final String SERVER_LOCAL_FOR_EMULATOR = "10.0.2.2"; + } + public static final class Messages { private Messages() { } @@ -43,7 +52,8 @@ final class Protocol { private Commands() { } - public static final String PAIR = "LO_SERVER_CLIENT_PAIR"; + public static final String PAIR_WITH_SERVER = "LO_SERVER_CLIENT_PAIR"; + public static final String SEARCH_SERVERS = "LOREMOTE_SEARCH"; public static final String TRANSITION_NEXT = "transition_next"; public static final String TRANSITION_PREVIOUS = "transition_previous"; diff --git a/android/sdremote/src/org/libreoffice/impressremote/communication/ServerFinder.java b/android/sdremote/src/org/libreoffice/impressremote/communication/ServerFinder.java index f1726ad85474..9ac70376e1a6 100644 --- a/android/sdremote/src/org/libreoffice/impressremote/communication/ServerFinder.java +++ b/android/sdremote/src/org/libreoffice/impressremote/communication/ServerFinder.java @@ -9,43 +9,161 @@ package org.libreoffice.impressremote.communication; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; import java.util.Collection; import java.util.HashMap; - -import org.libreoffice.impressremote.Globals; -import org.libreoffice.impressremote.communication.Server.Protocol; +import java.util.Map; import android.content.Context; import android.content.Intent; import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; -public class ServerFinder { +public class ServerFinder implements Runnable { + private final Context mContext; - private Context mContext; + private DatagramSocket mSocket = null; + private Thread mListenerThread; + private boolean mFinishRequested; - private static final int PORT = 1598; - private static final String GROUPADDRESS = "239.0.0.1"; + private final Map<String, Server> mServers; - private static final String CHARSET = "UTF-8"; + public ServerFinder(Context aContext) { + mContext = aContext; - private static final long SEARCH_INTERVAL = 1000 * 15; + mSocket = null; + mListenerThread = null; + mFinishRequested = false; - private DatagramSocket mSocket = null; + mServers = new HashMap<String, Server>(); + } - private Thread mListenerThread = null; + public void startSearch() { + if (mSocket != null) { + return; + } - private boolean mFinishRequested = false; + mFinishRequested = false; - private HashMap<String, Server> mServerList = new HashMap<String, Server>(); + if (mListenerThread == null) { + mListenerThread = new Thread(this); + } - public ServerFinder(Context aContext) { - mContext = aContext; + mListenerThread.start(); + } + + @Override + public void run() { + addLocalServerForEmulator(); + + long aStartSearchTime = 0; + + setUpSearchSocket(); + + while (!mFinishRequested) { + if (System + .currentTimeMillis() - aStartSearchTime > 1000 * 15) { + sendSearchCommand(); + + aStartSearchTime = System.currentTimeMillis(); + + removeStaleServers(); + } + + listenForServer(); + } + } + + /** + * Check whether we are on an emulator and add it's host to the list of + * servers if so (although we do not know whether libo is running on + * the host). + */ + private void addLocalServerForEmulator() { + if (!isLocalServerForEmulatorReachable()) { + return; + } + + Server aServer = new Server(Server.Protocol.NETWORK, + Protocol.Addresses.SERVER_LOCAL_FOR_EMULATOR, "Android Emulator", + 0); + + mServers.put(aServer.getAddress(), aServer); + + callUpdatingServersList(); + } + + private boolean isLocalServerForEmulatorReachable() { + try { + InetAddress aLocalServerAddress = InetAddress + .getByName(Protocol.Addresses.SERVER_LOCAL_FOR_EMULATOR); + + return aLocalServerAddress.isReachable(100); + } catch (UnknownHostException e) { + return false; + } catch (IOException e) { + return false; + } + } + + private void callUpdatingServersList() { + Intent aIntent = new Intent( + CommunicationService.MSG_SERVERLIST_CHANGED); + LocalBroadcastManager.getInstance(mContext).sendBroadcast(aIntent); + } + + private void setUpSearchSocket() { + try { + mSocket = new DatagramSocket(); + mSocket.setSoTimeout(1000 * 10); + } catch (SocketException e) { + throw new RuntimeException("Unable to open search socket."); + } + } + + private void sendSearchCommand() { + try { + mSocket.send(buildSearchPacket()); + } catch (IOException e) { + throw new RuntimeException("Unable to send search packet."); + } + } + + private DatagramPacket buildSearchPacket() { + try { + String aSearchCommand = Protocol.Commands + .prepareCommand(Protocol.Commands.SEARCH_SERVERS); + + DatagramPacket aSearchPacket = new DatagramPacket( + aSearchCommand.getBytes(), aSearchCommand.length()); + aSearchPacket.setAddress( + InetAddress.getByName(Protocol.Addresses.SERVER_SEARCH)); + aSearchPacket.setPort(Protocol.Ports.SERVER_SEARCH); + + return aSearchPacket; + } catch (UnknownHostException e) { + throw new RuntimeException("Unable to find address to search."); + } + } + + private void removeStaleServers() { + for (Server aServer : mServers.values()) { + if (aServer.mNoTimeout) { + continue; + } + + if (System.currentTimeMillis() + - aServer + .getTimeDiscovered() > 60 * 1000) { + mServers + .remove(aServer.getAddress()); + callUpdatingServersList(); + } + } } private void listenForServer() { @@ -59,7 +177,8 @@ public class ServerFinder { int i; for (i = 0; i < aBuffer.length; i++) { if (aPacket.getData()[i] == '\n') { - aCommand = new String(aPacket.getData(), 0, i, CHARSET); + aCommand = new String(aPacket.getData(), 0, i, + Protocol.CHARSET); break; } } @@ -69,7 +188,7 @@ public class ServerFinder { for (int j = i + 1; j < aBuffer.length; j++) { if (aPacket.getData()[j] == '\n') { aName = new String(aPacket.getData(), i + 1, j - (i + 1), - CHARSET); + Protocol.CHARSET); break; } } @@ -77,13 +196,12 @@ public class ServerFinder { return; } Server aServer = new Server(Server.Protocol.NETWORK, aPacket - .getAddress().getHostAddress(), aName, - System.currentTimeMillis()); - mServerList.put(aServer.getAddress(), aServer); - Log.i(Globals.TAG, "ServerFinder.listenForServer: contains " + aName); + .getAddress().getHostAddress(), aName, + System.currentTimeMillis()); + mServers.put(aServer.getAddress(), aServer); - notifyActivity(); - } catch (java.net.SocketTimeoutException e) { + callUpdatingServersList(); + } catch (SocketTimeoutException e) { // Ignore -- we want to timeout to enable checking whether we // should stop listening periodically } catch (IOException e) { @@ -91,100 +209,17 @@ public class ServerFinder { } - public void startFinding() { - if (mSocket != null) - return; - - mFinishRequested = false; - + public void stopSearch() { if (mListenerThread == null) { - mListenerThread = new Thread() { - @Override - public void run() { - checkAndAddEmulator(); - long aTime = 0; - try { - mSocket = new DatagramSocket(); - mSocket.setSoTimeout(1000 * 10); - while (!mFinishRequested) { - if (System.currentTimeMillis() - aTime > SEARCH_INTERVAL) { - String aString = "LOREMOTE_SEARCH\n"; - DatagramPacket aPacket = new DatagramPacket( - aString.getBytes(CHARSET), - aString.length(), - InetAddress.getByName(GROUPADDRESS), - PORT); - mSocket.send(aPacket); - aTime = System.currentTimeMillis(); - // Remove stale servers - for (Server aServer : mServerList.values()) { - if (!aServer.mNoTimeout - && System.currentTimeMillis() - - aServer.getTimeDiscovered() > 60 * 1000) { - mServerList.remove(aServer.getAddress()); - notifyActivity(); - - } - } - } - - listenForServer(); - } - } catch (SocketException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (UnsupportedEncodingException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } - }; - mListenerThread.start(); - } - - } - - public void stopFinding() { - if (mListenerThread != null) { - mFinishRequested = true; - mListenerThread = null; - } - } - - /** - * Check whether we are on an emulator and add it's host to the list of - * servers if so (although we do not know whether libo is running on - * the host). - */ - private void checkAndAddEmulator() { - try { - if (InetAddress.getByName("10.0.2.2").isReachable(100)) { - Log.i(Globals.TAG, "ServerFinder.checkAndAddEmulator: NulledNot, whatever that is supposed to mean"); - Server aServer = new Server(Protocol.NETWORK, "10.0.2.2", - "Android Emulator Host", 0); - aServer.mNoTimeout = true; - mServerList.put(aServer.getAddress(), aServer); - notifyActivity(); - } - } catch (IOException e) { - // Probably means we can't connect -- i.e. no emulator host + return; } - } - /** - * Notify the activity that the server list has changed. - */ - private void notifyActivity() { - Intent aIntent = new Intent(CommunicationService.MSG_SERVERLIST_CHANGED); - LocalBroadcastManager.getInstance(mContext).sendBroadcast(aIntent); + mFinishRequested = true; + mListenerThread = null; } - public Collection<Server> getServerList() { - return mServerList.values(); + public Collection<Server> getServers() { + return mServers.values(); } } |