From 2d28dcada205cc77279a3a1ddb3950e20932a099 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 16 Dec 2015 13:48:56 -0200 Subject: [PATCH 1/2] Create two new events to signal enabling and disabling of transports --- briar-android/res/values/strings.xml | 4 ++ .../android/DashboardActivity.java | 43 ++++++++++++++++++- .../plugins/droidtooth/DroidtoothPlugin.java | 4 +- .../briarproject/plugins/tor/TorPlugin.java | 11 +++-- .../api/event/TransportDisabledEvent.java | 17 ++++++++ .../api/event/TransportEnabledEvent.java | 17 ++++++++ .../api/plugins/PluginCallback.java | 7 ++- .../plugins/PluginManagerImpl.java | 15 ++++++- .../briarproject/plugins/tcp/TcpPlugin.java | 4 +- .../plugins/bluetooth/BluetoothPlugin.java | 4 +- .../plugins/DuplexClientTest.java | 6 ++- .../plugins/DuplexServerTest.java | 6 ++- .../plugins/PluginManagerImplTest.java | 6 ++- .../plugins/tcp/LanTcpPluginTest.java | 6 ++- 14 files changed, 132 insertions(+), 18 deletions(-) create mode 100644 briar-api/src/org/briarproject/api/event/TransportDisabledEvent.java create mode 100644 briar-api/src/org/briarproject/api/event/TransportEnabledEvent.java diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index 0ce4e1c57..85fe74090 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -116,6 +116,10 @@ Online Offline Send + Data Transports + Internet via Tor + Bluetooth + Local Area Network Lost password diff --git a/briar-android/src/org/briarproject/android/DashboardActivity.java b/briar-android/src/org/briarproject/android/DashboardActivity.java index fc9d05b88..b499c6794 100644 --- a/briar-android/src/org/briarproject/android/DashboardActivity.java +++ b/briar-android/src/org/briarproject/android/DashboardActivity.java @@ -18,9 +18,19 @@ import org.briarproject.android.contact.ContactListActivity; import org.briarproject.android.forum.ForumListActivity; import org.briarproject.android.util.LayoutUtils; import org.briarproject.api.LocalAuthor; +import org.briarproject.api.TransportId; import org.briarproject.api.android.ReferenceManager; import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; +import org.briarproject.api.event.Event; +import org.briarproject.api.event.EventBus; +import org.briarproject.api.event.EventListener; +import org.briarproject.api.event.TransportAddedEvent; +import org.briarproject.api.event.TransportDisabledEvent; +import org.briarproject.api.event.TransportEnabledEvent; +import org.briarproject.api.event.TransportRemovedEvent; +import org.briarproject.api.plugins.Plugin; +import org.briarproject.api.plugins.PluginManager; import java.util.ArrayList; import java.util.List; @@ -34,15 +44,17 @@ import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH; -public class DashboardActivity extends BriarActivity { +public class DashboardActivity extends BriarActivity implements EventListener { private static final Logger LOG = Logger.getLogger(DashboardActivity.class.getName()); @Inject private ReferenceManager referenceManager; + @Inject private PluginManager pluginManager; // Fields that are accessed from background threads must be volatile @Inject private volatile DatabaseComponent db; + @Inject private volatile EventBus eventBus; @Override public void onCreate(Bundle state) { @@ -50,12 +62,41 @@ public class DashboardActivity extends BriarActivity { handleIntent(getIntent()); } + @Override + public void onResume() { + super.onResume(); + + eventBus.addListener(this); + } + + @Override + public void onPause() { + super.onPause(); + + eventBus.removeListener(this); + } + @Override public void onNewIntent(Intent i) { super.onNewIntent(i); handleIntent(i); } + @Override + public void eventOccurred(Event e) { + if (e instanceof TransportEnabledEvent) { + TransportId id = ((TransportEnabledEvent) e).getTransportId(); + if (LOG.isLoggable(INFO)) { + LOG.info("TransportEnabledEvent: " + id.getString()); + } + } else if (e instanceof TransportDisabledEvent) { + TransportId id = ((TransportDisabledEvent) e).getTransportId(); + if (LOG.isLoggable(INFO)) { + LOG.info("TransportDisabledEvent: " + id.getString()); + } + } + } + private void handleIntent(Intent i) { boolean failed = i.getBooleanExtra("briar.STARTUP_FAILED", false); long handle = i.getLongExtra("briar.LOCAL_AUTHOR_HANDLE", -1); diff --git a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java b/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java index 4191e3561..06dfd1dc9 100644 --- a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java +++ b/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPlugin.java @@ -172,7 +172,7 @@ class DroidtoothPlugin implements DuplexPlugin { } LOG.info("Socket bound"); socket = ss; - callback.pollNow(); + callback.transportEnabled(); acceptContactConnections(); } }); @@ -196,6 +196,8 @@ class DroidtoothPlugin implements DuplexPlugin { if (ss != null) ss.close(); } catch (IOException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } finally { + callback.transportDisabled(); } } diff --git a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java index ffd6919db..ebd954dfa 100644 --- a/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java +++ b/briar-android/src/org/briarproject/plugins/tor/TorPlugin.java @@ -391,6 +391,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, if (ss != null) ss.close(); } catch (IOException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } finally { + callback.transportDisabled(); } } @@ -459,7 +461,10 @@ class TorPlugin implements DuplexPlugin, EventHandler, private void enableNetwork(boolean enable) throws IOException { if (!running) return; if (LOG.isLoggable(INFO)) LOG.info("Enabling network: " + enable); - if (!enable) circuitBuilt.set(false); + if (!enable) { + circuitBuilt.set(false); + callback.transportDisabled(); + } networkEnabled = enable; controlConnection.setConf("DisableNetwork", enable ? "0" : "1"); } @@ -549,7 +554,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, public void circuitStatus(String status, String id, String path) { if (status.equals("BUILT") && !circuitBuilt.getAndSet(true)) { LOG.info("First circuit built"); - if (isRunning()) callback.pollNow(); + if (isRunning()) callback.transportEnabled(); } } @@ -567,7 +572,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg); if (severity.equals("NOTICE") && msg.startsWith("Bootstrapped 100%")) { bootstrapped = true; - if (isRunning()) callback.pollNow(); + if (isRunning()) callback.transportEnabled(); } } diff --git a/briar-api/src/org/briarproject/api/event/TransportDisabledEvent.java b/briar-api/src/org/briarproject/api/event/TransportDisabledEvent.java new file mode 100644 index 000000000..1efb575fd --- /dev/null +++ b/briar-api/src/org/briarproject/api/event/TransportDisabledEvent.java @@ -0,0 +1,17 @@ +package org.briarproject.api.event; + +import org.briarproject.api.TransportId; + +/** An event that is broadcast when a transport is disabled. */ +public class TransportDisabledEvent extends Event { + + private final TransportId transportId; + + public TransportDisabledEvent(TransportId transportId) { + this.transportId = transportId; + } + + public TransportId getTransportId() { + return transportId; + } +} diff --git a/briar-api/src/org/briarproject/api/event/TransportEnabledEvent.java b/briar-api/src/org/briarproject/api/event/TransportEnabledEvent.java new file mode 100644 index 000000000..7a72d8358 --- /dev/null +++ b/briar-api/src/org/briarproject/api/event/TransportEnabledEvent.java @@ -0,0 +1,17 @@ +package org.briarproject.api.event; + +import org.briarproject.api.TransportId; + +/** An event that is broadcast when a transport is enabled. */ +public class TransportEnabledEvent extends Event { + + private final TransportId transportId; + + public TransportEnabledEvent(TransportId transportId) { + this.transportId = transportId; + } + + public TransportId getTransportId() { + return transportId; + } +} diff --git a/briar-api/src/org/briarproject/api/plugins/PluginCallback.java b/briar-api/src/org/briarproject/api/plugins/PluginCallback.java index 3a5890b2d..34361a2ca 100644 --- a/briar-api/src/org/briarproject/api/plugins/PluginCallback.java +++ b/briar-api/src/org/briarproject/api/plugins/PluginCallback.java @@ -50,6 +50,9 @@ public interface PluginCallback { */ void showMessage(String... message); - /** Schedules the plugin to be polled immediately. */ - void pollNow(); + /** Signal that the transport got enabled. */ + void transportEnabled(); + + /** Signal that the transport got disabled. */ + void transportDisabled(); } diff --git a/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java b/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java index 534480848..4742d8251 100644 --- a/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java +++ b/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java @@ -6,6 +6,9 @@ import org.briarproject.api.TransportId; import org.briarproject.api.TransportProperties; import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; +import org.briarproject.api.event.EventBus; +import org.briarproject.api.event.TransportDisabledEvent; +import org.briarproject.api.event.TransportEnabledEvent; import org.briarproject.api.lifecycle.IoExecutor; import org.briarproject.api.plugins.ConnectionManager; import org.briarproject.api.plugins.Plugin; @@ -48,6 +51,7 @@ class PluginManagerImpl implements PluginManager { Logger.getLogger(PluginManagerImpl.class.getName()); private final Executor ioExecutor; + private final EventBus eventBus; private final SimplexPluginConfig simplexPluginConfig; private final DuplexPluginConfig duplexPluginConfig; private final Clock clock; @@ -60,12 +64,13 @@ class PluginManagerImpl implements PluginManager { private final List duplexPlugins; @Inject - PluginManagerImpl(@IoExecutor Executor ioExecutor, + PluginManagerImpl(@IoExecutor Executor ioExecutor, EventBus eventBus, SimplexPluginConfig simplexPluginConfig, DuplexPluginConfig duplexPluginConfig, Clock clock, DatabaseComponent db, Poller poller, ConnectionManager connectionManager, UiCallback uiCallback) { this.ioExecutor = ioExecutor; + this.eventBus = eventBus; this.simplexPluginConfig = simplexPluginConfig; this.duplexPluginConfig = duplexPluginConfig; this.clock = clock; @@ -360,10 +365,16 @@ class PluginManagerImpl implements PluginManager { uiCallback.showMessage(message); } - public void pollNow() { + public void transportEnabled() { + eventBus.broadcast(new TransportEnabledEvent(id)); + Plugin p = plugins.get(id); if (p != null) poller.pollNow(p); } + + public void transportDisabled() { + eventBus.broadcast(new TransportDisabledEvent(id)); + } } private class SimplexCallback extends PluginCallbackImpl diff --git a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java index 369b5a6d2..48f731464 100644 --- a/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java +++ b/briar-core/src/org/briarproject/plugins/tcp/TcpPlugin.java @@ -106,7 +106,7 @@ abstract class TcpPlugin implements DuplexPlugin { SocketAddress local = ss.getLocalSocketAddress(); setLocalSocketAddress((InetSocketAddress) local); if (LOG.isLoggable(INFO)) LOG.info("Listening on " + local); - callback.pollNow(); + callback.transportEnabled(); acceptContactConnections(); } }); @@ -117,6 +117,8 @@ abstract class TcpPlugin implements DuplexPlugin { if (ss != null) ss.close(); } catch (IOException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } finally { + callback.transportDisabled(); } } diff --git a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java b/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java index 3db1dfebf..792db1398 100644 --- a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java +++ b/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPlugin.java @@ -117,7 +117,7 @@ class BluetoothPlugin implements DuplexPlugin { return; } socket = ss; - callback.pollNow(); + callback.transportEnabled(); acceptContactConnections(ss); } }); @@ -145,6 +145,8 @@ class BluetoothPlugin implements DuplexPlugin { if (ss != null) ss.close(); } catch (IOException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } finally { + callback.transportDisabled(); } } diff --git a/briar-tests/src/org/briarproject/plugins/DuplexClientTest.java b/briar-tests/src/org/briarproject/plugins/DuplexClientTest.java index e36624a5d..a32cf9683 100644 --- a/briar-tests/src/org/briarproject/plugins/DuplexClientTest.java +++ b/briar-tests/src/org/briarproject/plugins/DuplexClientTest.java @@ -100,11 +100,13 @@ public abstract class DuplexClientTest extends DuplexTest { public void showMessage(String... message) {} - public void pollNow() {} - public void incomingConnectionCreated(DuplexTransportConnection d) {} public void outgoingConnectionCreated(ContactId contactId, DuplexTransportConnection d) {} + + public void transportEnabled() {} + + public void transportDisabled() {} } } diff --git a/briar-tests/src/org/briarproject/plugins/DuplexServerTest.java b/briar-tests/src/org/briarproject/plugins/DuplexServerTest.java index ba73b0ace..daf3c4740 100644 --- a/briar-tests/src/org/briarproject/plugins/DuplexServerTest.java +++ b/briar-tests/src/org/briarproject/plugins/DuplexServerTest.java @@ -99,8 +99,6 @@ public abstract class DuplexServerTest extends DuplexTest { public void showMessage(String... message) {} - public void pollNow() {} - public void incomingConnectionCreated(DuplexTransportConnection d) { System.out.println("Connection received"); sendChallengeReceiveResponse(d); @@ -109,5 +107,9 @@ public abstract class DuplexServerTest extends DuplexTest { public void outgoingConnectionCreated(ContactId c, DuplexTransportConnection d) {} + + public void transportEnabled() {} + + public void transportDisabled() {} } } diff --git a/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java b/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java index 5493a0178..1394a998b 100644 --- a/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java +++ b/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java @@ -3,6 +3,8 @@ package org.briarproject.plugins; import org.briarproject.BriarTestCase; import org.briarproject.api.TransportId; import org.briarproject.api.db.DatabaseComponent; +import org.briarproject.api.event.EventBus; +import org.briarproject.api.lifecycle.IoExecutor; import org.briarproject.api.plugins.ConnectionManager; import org.briarproject.api.plugins.duplex.DuplexPlugin; import org.briarproject.api.plugins.duplex.DuplexPluginCallback; @@ -32,6 +34,7 @@ public class PluginManagerImplTest extends BriarTestCase { Clock clock = new SystemClock(); Mockery context = new Mockery(); final Executor ioExecutor = Executors.newCachedThreadPool(); + final EventBus eventBus = context.mock(EventBus.class); final SimplexPluginConfig simplexPluginConfig = context.mock(SimplexPluginConfig.class); final DuplexPluginConfig duplexPluginConfig = @@ -121,9 +124,10 @@ public class PluginManagerImplTest extends BriarTestCase { oneOf(simplexPlugin).stop(); oneOf(duplexPlugin).stop(); }}); - PluginManagerImpl p = new PluginManagerImpl(ioExecutor, + PluginManagerImpl p = new PluginManagerImpl(ioExecutor, eventBus, simplexPluginConfig, duplexPluginConfig, clock, db, poller, dispatcher, uiCallback); + // Two plugins should be started and stopped assertTrue(p.start()); assertTrue(p.stop()); diff --git a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java index b929c8f52..575b8f136 100644 --- a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java +++ b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java @@ -205,13 +205,15 @@ public class LanTcpPluginTest extends BriarTestCase { public void showMessage(String... message) {} - public void pollNow() {} - public void incomingConnectionCreated(DuplexTransportConnection d) { connectionsLatch.countDown(); } public void outgoingConnectionCreated(ContactId c, DuplexTransportConnection d) {} + + public void transportEnabled() {} + + public void transportDisabled() {} } } From 264285ecf7f06af6b20795f1a4a2faecfeb2a72d Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 16 Dec 2015 18:49:57 -0200 Subject: [PATCH 2/2] Show all transports on the dashboard and indicate which transports are currently available. The icons have been chosen from the official material icons and might be replaced later with icons that better represent the given transport. Please note that I used vector drawables which will be automatically converted at build time to raster graphics. Closes #96 --- briar-android/res/drawable/transport_bt.xml | 5 + briar-android/res/drawable/transport_lan.xml | 6 + briar-android/res/drawable/transport_tor.xml | 5 + .../res/layout/list_item_transport.xml | 27 ++++ briar-android/res/layout/transports_list.xml | 20 +++ briar-android/res/values/strings.xml | 4 +- .../android/DashboardActivity.java | 137 +++++++++++++++++- 7 files changed, 198 insertions(+), 6 deletions(-) create mode 100644 briar-android/res/drawable/transport_bt.xml create mode 100644 briar-android/res/drawable/transport_lan.xml create mode 100644 briar-android/res/drawable/transport_tor.xml create mode 100644 briar-android/res/layout/list_item_transport.xml create mode 100644 briar-android/res/layout/transports_list.xml diff --git a/briar-android/res/drawable/transport_bt.xml b/briar-android/res/drawable/transport_bt.xml new file mode 100644 index 000000000..d22170869 --- /dev/null +++ b/briar-android/res/drawable/transport_bt.xml @@ -0,0 +1,5 @@ + + + diff --git a/briar-android/res/drawable/transport_lan.xml b/briar-android/res/drawable/transport_lan.xml new file mode 100644 index 000000000..d2cc9189e --- /dev/null +++ b/briar-android/res/drawable/transport_lan.xml @@ -0,0 +1,6 @@ + + + + diff --git a/briar-android/res/drawable/transport_tor.xml b/briar-android/res/drawable/transport_tor.xml new file mode 100644 index 000000000..fe462b2f7 --- /dev/null +++ b/briar-android/res/drawable/transport_tor.xml @@ -0,0 +1,5 @@ + + + diff --git a/briar-android/res/layout/list_item_transport.xml b/briar-android/res/layout/list_item_transport.xml new file mode 100644 index 000000000..11c3d5e4d --- /dev/null +++ b/briar-android/res/layout/list_item_transport.xml @@ -0,0 +1,27 @@ + + + + + + + + \ No newline at end of file diff --git a/briar-android/res/layout/transports_list.xml b/briar-android/res/layout/transports_list.xml new file mode 100644 index 000000000..02c05e74d --- /dev/null +++ b/briar-android/res/layout/transports_list.xml @@ -0,0 +1,20 @@ + + + + + + + + diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index 85fe74090..bdcf26104 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -117,9 +117,9 @@ Offline Send Data Transports - Internet via Tor + Internet Bluetooth - Local Area Network + Wi-Fi Lost password diff --git a/briar-android/src/org/briarproject/android/DashboardActivity.java b/briar-android/src/org/briarproject/android/DashboardActivity.java index b499c6794..6e08cd217 100644 --- a/briar-android/src/org/briarproject/android/DashboardActivity.java +++ b/briar-android/src/org/briarproject/android/DashboardActivity.java @@ -1,17 +1,21 @@ package org.briarproject.android; +import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; +import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.GridView; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; +import android.widget.TextView; import org.briarproject.R; import org.briarproject.android.contact.ContactListActivity; @@ -25,10 +29,8 @@ import org.briarproject.api.db.DbException; import org.briarproject.api.event.Event; import org.briarproject.api.event.EventBus; import org.briarproject.api.event.EventListener; -import org.briarproject.api.event.TransportAddedEvent; import org.briarproject.api.event.TransportDisabledEvent; import org.briarproject.api.event.TransportEnabledEvent; -import org.briarproject.api.event.TransportRemovedEvent; import org.briarproject.api.plugins.Plugin; import org.briarproject.api.plugins.PluginManager; @@ -40,6 +42,7 @@ import javax.inject.Inject; import static android.view.Gravity.CENTER; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH; @@ -49,6 +52,9 @@ public class DashboardActivity extends BriarActivity implements EventListener { private static final Logger LOG = Logger.getLogger(DashboardActivity.class.getName()); + private List transports; + private BaseAdapter transportsAdapter; + @Inject private ReferenceManager referenceManager; @Inject private PluginManager pluginManager; @@ -89,11 +95,13 @@ public class DashboardActivity extends BriarActivity implements EventListener { if (LOG.isLoggable(INFO)) { LOG.info("TransportEnabledEvent: " + id.getString()); } + setTransport(id, true); } else if (e instanceof TransportDisabledEvent) { TransportId id = ((TransportDisabledEvent) e).getTransportId(); if (LOG.isLoggable(INFO)) { LOG.info("TransportDisabledEvent: " + id.getString()); } + setTransport(id, false); } } @@ -185,8 +193,14 @@ public class DashboardActivity extends BriarActivity implements EventListener { int pad = LayoutUtils.getPadding(this); + LinearLayout layout = new LinearLayout(this); + layout.setLayoutParams(MATCH_MATCH); + layout.setOrientation(LinearLayout.VERTICAL); + GridView grid = new GridView(this); - grid.setLayoutParams(matchMatch); + LinearLayout.LayoutParams params = + new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT, 1f); + grid.setLayoutParams(params); grid.setGravity(CENTER); grid.setPadding(pad, pad, pad, pad); Resources res = getResources(); @@ -211,7 +225,21 @@ public class DashboardActivity extends BriarActivity implements EventListener { return buttons.get(position); } }); - setContentView(grid); + layout.addView(grid); + + // inflate transports layout + LayoutInflater inflater = (LayoutInflater) getSystemService + (Context.LAYOUT_INFLATER_SERVICE); + ViewGroup transportsLayout = (ViewGroup) inflater. + inflate(R.layout.transports_list, layout); + + initializeTransports(); + + GridView transportsView = (GridView) transportsLayout.findViewById( + R.id.transportsView); + transportsView.setAdapter(transportsAdapter); + + setContentView(layout); } private void showSpinner() { @@ -247,4 +275,105 @@ public class DashboardActivity extends BriarActivity implements EventListener { } }); } + + private void initializeTransports() { + transports = new ArrayList(3); + + Transport tor = new Transport(); + tor.id = new TransportId("tor"); + Plugin torPlugin = pluginManager.getPlugin(tor.id); + if (torPlugin == null) tor.enabled = false; + else tor.enabled = torPlugin.isRunning(); + tor.iconId = R.drawable.transport_tor; + tor.textId = R.string.transport_tor; + transports.add(tor); + + Transport bt = new Transport(); + bt.id = new TransportId("bt"); + Plugin btPlugin = pluginManager.getPlugin(bt.id); + if (btPlugin == null) bt.enabled = false; + else bt.enabled = btPlugin.isRunning(); + bt.iconId = R.drawable.transport_bt; + bt.textId = R.string.transport_bt; + transports.add(bt); + + Transport lan = new Transport(); + lan.id = new TransportId("lan"); + Plugin lanPlugin = pluginManager.getPlugin(lan.id); + if (lanPlugin == null) lan.enabled = false; + else lan.enabled = lanPlugin.isRunning(); + lan.iconId = R.drawable.transport_lan; + lan.textId = R.string.transport_lan; + transports.add(lan); + + transportsAdapter = new BaseAdapter() { + @Override + public int getCount() { + return transports.size(); + } + + @Override + public Transport getItem(int position) { + return transports.get(position); + } + + @Override + public long getItemId(int position) { + return 0; + } + + @Override + public View getView(int position, View convertView, + ViewGroup parent) { + LayoutInflater inflater = (LayoutInflater) getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + ViewGroup view = (ViewGroup) inflater + .inflate(R.layout.list_item_transport, parent, false); + + Transport t = getItem(position); + Resources r = getResources(); + + int c; + if (t.enabled) { + c = r.getColor(R.color.briar_green_light); + } else { + c = r.getColor(android.R.color.tertiary_text_light); + } + + ImageView icon = (ImageView) view.findViewById(R.id.imageView); + icon.setImageDrawable(r.getDrawable(t.iconId)); + icon.setColorFilter(c); + + TextView text = (TextView) view.findViewById(R.id.textView); + text.setText(getString(t.textId)); + text.setTextColor(c); + + return view; + } + }; + } + + private void setTransport(final TransportId id, final boolean enabled) { + runOnUiThread(new Runnable() { + public void run() { + if (transports == null || transportsAdapter == null) return; + + for (Transport t : transports) { + if (t.id.equals(id)) { + t.enabled = enabled; + break; + } + } + + transportsAdapter.notifyDataSetChanged(); + } + }); + } + + private static class Transport { + TransportId id; + boolean enabled; + int iconId; + int textId; + } }