Added debugging screen to alpha and beta builds. Dev task #73.

This commit is contained in:
akwizgran
2014-02-28 23:44:35 +00:00
parent 07b4d9b5d8
commit a2d099ea17
20 changed files with 440 additions and 43 deletions

View File

@@ -12,6 +12,9 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<!-- FIXME: Only needed for alpha and beta builds -->
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:theme="@style/LightTheme"
@@ -54,6 +57,11 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".android.TestingActivity"
android:logo="@drawable/logo"
android:label="@string/app_name" >
</activity>
<activity
android:name=".android.contact.ContactListActivity"
android:logo="@drawable/logo"

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -4,6 +4,7 @@
<color name="action_bar_text">#FFFFFF</color>
<color name="action_bar_background">#2D3E50</color>
<color name="button_bar_background">#FFFFFF</color>
<color name="dashboard_background">#FFFFFF</color>
<color name="private_message_background">#FFFFFF</color>
<color name="private_message_date">#AAAAAA</color>
<color name="unread_background">#FFFFFF</color>

View File

@@ -16,7 +16,7 @@
<string name="expiry_warning">This software has expired.\nPlease install a newer version.</string>
<string name="contact_list_button">Contacts</string>
<string name="forums_button">Forums</string>
<string name="synchronize_button">Synchronize</string>
<string name="testing_button">Testing</string>
<string name="sign_out_button">Sign Out</string>
<string name="contact_list_title">Contacts</string>
<string name="no_contacts">No contacts</string>

View File

@@ -2,7 +2,6 @@ package org.briarproject.android;
import static android.view.Gravity.CENTER;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.widget.Toast.LENGTH_SHORT;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
@@ -37,7 +36,6 @@ import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Toast;
public class DashboardActivity extends BriarActivity {
@@ -121,20 +119,19 @@ public class DashboardActivity extends BriarActivity {
});
buttons.add(forumsButton);
Button syncButton = new Button(this);
syncButton.setLayoutParams(matchMatch);
syncButton.setBackgroundResource(0);
syncButton.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.navigation_refresh, 0, 0);
syncButton.setText(R.string.synchronize_button);
syncButton.setOnClickListener(new OnClickListener() {
Button testingButton = new Button(this);
testingButton.setLayoutParams(matchMatch);
testingButton.setBackgroundResource(0);
testingButton.setCompoundDrawablesWithIntrinsicBounds(0,
R.drawable.action_help, 0, 0);
testingButton.setText(R.string.testing_button);
testingButton.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
// FIXME: Hook this button up to an activity
Toast.makeText(DashboardActivity.this,
R.string.not_implemented_toast, LENGTH_SHORT).show();
startActivity(new Intent(DashboardActivity.this,
TestingActivity.class));
}
});
buttons.add(syncButton);
buttons.add(testingButton);
Button signOutButton = new Button(this);
signOutButton.setLayoutParams(matchMatch);
@@ -157,7 +154,7 @@ public class DashboardActivity extends BriarActivity {
grid.setGravity(CENTER);
grid.setPadding(pad, pad, pad, pad);
Resources res = getResources();
grid.setBackgroundColor(res.getColor(R.color.button_bar_background));
grid.setBackgroundColor(res.getColor(R.color.dashboard_background));
grid.setNumColumns(2);
grid.setAdapter(new BaseAdapter() {

View File

@@ -0,0 +1,347 @@
package org.briarproject.android;
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE;
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
import static android.content.Intent.ACTION_SEND;
import static android.content.Intent.EXTRA_EMAIL;
import static android.content.Intent.EXTRA_STREAM;
import static android.content.Intent.EXTRA_SUBJECT;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
import static android.view.Gravity.CENTER;
import static android.view.Gravity.CENTER_HORIZONTAL;
import static android.widget.LinearLayout.VERTICAL;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP;
import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.logging.Logger;
import javax.inject.Inject;
import org.briarproject.R;
import org.briarproject.android.util.ElasticHorizontalSpace;
import org.briarproject.android.util.HorizontalBorder;
import org.briarproject.android.util.LayoutUtils;
import org.briarproject.api.TransportId;
import org.briarproject.api.android.AndroidExecutor;
import org.briarproject.api.plugins.Plugin;
import org.briarproject.api.plugins.PluginManager;
import org.briarproject.util.StringUtils;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
public class TestingActivity extends BriarActivity implements OnClickListener {
private static final Logger LOG =
Logger.getLogger(TestingActivity.class.getName());
@Inject private AndroidExecutor androidExecutor;
@Inject private PluginManager pluginManager;
private ScrollView scroll = null;
private LinearLayout status = null;
private ImageButton refresh = null, share = null;
private File temp = null;
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
LinearLayout layout = new LinearLayout(this);
layout.setLayoutParams(MATCH_MATCH);
layout.setOrientation(VERTICAL);
layout.setGravity(CENTER_HORIZONTAL);
scroll = new ScrollView(this);
scroll.setLayoutParams(MATCH_WRAP_1);
status = new LinearLayout(this);
status.setOrientation(VERTICAL);
status.setGravity(CENTER_HORIZONTAL);
int pad = LayoutUtils.getPadding(this);
status.setPadding(pad, pad, pad, pad);
scroll.addView(status);
layout.addView(scroll);
layout.addView(new HorizontalBorder(this));
LinearLayout footer = new LinearLayout(this);
footer.setLayoutParams(MATCH_WRAP);
footer.setGravity(CENTER);
Resources res = getResources();
footer.setBackgroundColor(res.getColor(R.color.button_bar_background));
footer.addView(new ElasticHorizontalSpace(this));
refresh = new ImageButton(this);
refresh.setBackgroundResource(0);
refresh.setImageResource(R.drawable.navigation_refresh);
refresh.setOnClickListener(this);
footer.addView(refresh);
footer.addView(new ElasticHorizontalSpace(this));
share = new ImageButton(this);
share.setBackgroundResource(0);
share.setImageResource(R.drawable.social_share);
share.setOnClickListener(this);
footer.addView(share);
footer.addView(new ElasticHorizontalSpace(this));
layout.addView(footer);
setContentView(layout);
}
@Override
public void onResume() {
super.onResume();
refresh();
}
@Override
public void onDestroy() {
super.onDestroy();
if(temp != null) temp.delete();
}
public void onClick(View view) {
if(view == refresh) refresh();
else if(view == share) share();
}
private void refresh() {
status.removeAllViews();
new AsyncTask<Void, Void, Map<String, String>>() {
protected Map<String, String> doInBackground(Void... args) {
return getStatusMap();
}
protected void onPostExecute(Map<String, String> result) {
int pad = LayoutUtils.getPadding(TestingActivity.this);
for(Entry<String, String> e : result.entrySet()) {
TextView title = new TextView(TestingActivity.this);
title.setTextSize(18);
title.setText(e.getKey());
status.addView(title);
TextView content = new TextView(TestingActivity.this);
content.setPadding(0, 0, 0, pad);
content.setText(e.getValue());
status.addView(content);
}
scroll.scrollTo(0, 0);
}
}.execute();
}
private Map<String, String> getStatusMap() {
Map<String, String> statusMap = new LinkedHashMap<String, String>();
// Is mobile data available?
Object o = getSystemService(CONNECTIVITY_SERVICE);
ConnectivityManager cm = (ConnectivityManager) o;
NetworkInfo mobile = cm.getNetworkInfo(TYPE_MOBILE);
boolean mobileAvailable = mobile != null && mobile.isAvailable();
// Is mobile data enabled?
boolean mobileEnabled = false;
try {
Class<?> clazz = Class.forName(cm.getClass().getName());
Method method = clazz.getDeclaredMethod("getMobileDataEnabled");
method.setAccessible(true);
mobileEnabled = (Boolean) method.invoke(cm);
} catch(ClassNotFoundException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch(NoSuchMethodException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch(IllegalAccessException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch(IllegalArgumentException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch(InvocationTargetException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
// Is mobile data connected ?
boolean mobileConnected = mobile != null && mobile.isConnected();
// Strings aren't loaded from resources as this activity is temporary
String mobileStatus;
if(mobileAvailable) mobileStatus = "Available, ";
else mobileStatus = "Not available, ";
if(mobileEnabled) mobileStatus += "enabled, ";
else mobileStatus += "not enabled, ";
if(mobileConnected) mobileStatus += "connected";
else mobileStatus += "not connected";
statusMap.put("Mobile data:", mobileStatus);
// Is wifi available?
NetworkInfo wifi = cm.getNetworkInfo(TYPE_WIFI);
boolean wifiAvailable = wifi != null && wifi.isAvailable();
// Is wifi enabled?
WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
boolean wifiEnabled = wm != null &&
wm.getWifiState() == WIFI_STATE_ENABLED;
// Is wifi connected?
boolean wifiConnected = wifi != null && wifi.isConnected();
String wifiStatus;
if(wifiAvailable) wifiStatus = "Available, ";
else wifiStatus = "Not available, ";
if(wifiEnabled) wifiStatus += "enabled, ";
else wifiStatus += "not enabled, ";
if(wifiConnected) wifiStatus += "connected";
else wifiStatus += "not connected";
statusMap.put("Wi-Fi:", wifiStatus);
// Is Bluetooth available?
BluetoothAdapter bt = null;
try {
bt = androidExecutor.call(new Callable<BluetoothAdapter>() {
public BluetoothAdapter call() throws Exception {
return BluetoothAdapter.getDefaultAdapter();
}
});
} catch(InterruptedException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch(ExecutionException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
boolean btAvailable = bt != null;
// Is Bluetooth enabled?
boolean btEnabled = bt != null && bt.isEnabled() &&
!StringUtils.isNullOrEmpty(bt.getAddress());
// Is Bluetooth connectable?
boolean btConnectable = bt != null &&
(bt.getScanMode() == SCAN_MODE_CONNECTABLE ||
bt.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE);
// Is Bluetooth discoverable?
boolean btDiscoverable = bt != null &&
bt.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE;
String btStatus;
if(btAvailable) btStatus = "Available, ";
else btStatus = "Not available, ";
if(btEnabled) btStatus += "enabled, ";
else btStatus += "not enabled, ";
if(btConnectable) btStatus += "connectable, ";
else btStatus += "not connectable, ";
if(btDiscoverable) btStatus += "discoverable";
else btStatus += "not discoverable";
statusMap.put("Bluetooth:", btStatus);
Plugin torPlugin = pluginManager.getPlugin(new TransportId("tor"));
boolean torPluginEnabled = torPlugin != null;
boolean torPluginRunning = torPlugin != null && torPlugin.isRunning();
String torPluginStatus;
if(torPluginEnabled) torPluginStatus = "Enabled, ";
else torPluginStatus = "Not enabled, ";
if(torPluginRunning) torPluginStatus += "running";
else torPluginStatus += "not running";
statusMap.put("Tor plugin:", torPluginStatus);
Plugin lanPlugin = pluginManager.getPlugin(new TransportId("lan"));
boolean lanPluginEnabled = lanPlugin != null;
boolean lanPluginRunning = lanPlugin != null && lanPlugin.isRunning();
String lanPluginStatus;
if(lanPluginEnabled) lanPluginStatus = "Enabled, ";
else lanPluginStatus = "Not enabled, ";
if(lanPluginRunning) lanPluginStatus += "running";
else lanPluginStatus += "not running";
statusMap.put("LAN plugin:", lanPluginStatus);
Plugin btPlugin = pluginManager.getPlugin(new TransportId("bt"));
boolean btPluginEnabled = btPlugin != null;
boolean btPluginRunning = btPlugin != null && btPlugin.isRunning();
String btPluginStatus;
if(btPluginEnabled) btPluginStatus = "Enabled, ";
else btPluginStatus = "Not enabled, ";
if(btPluginRunning) btPluginStatus += "running";
else btPluginStatus += "not running";
statusMap.put("Bluetooth plugin:", btPluginStatus);
StringBuilder log = new StringBuilder();
try {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("logcat -d -s TorPlugin");
Scanner scanner = new Scanner(process.getInputStream());
while(scanner.hasNextLine()) {
log.append(scanner.nextLine());
log.append('\n');
}
scanner.close();
} catch(IOException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
statusMap.put("Tor log:", log.toString());
return Collections.unmodifiableMap(statusMap);
}
private void share() {
new AsyncTask<Void, Void, Map<String, String>>() {
protected Map<String, String> doInBackground(Void... args) {
return getStatusMap();
}
protected void onPostExecute(Map<String, String> result) {
try {
File shared = Environment.getExternalStorageDirectory();
temp = File.createTempFile("debug", "txt", shared);
if(LOG.isLoggable(INFO))
LOG.info("Writing to " + temp.getPath());
PrintStream p = new PrintStream(new FileOutputStream(temp));
for(Entry<String, String> e : result.entrySet()) {
p.println(e.getKey());
p.println(e.getValue());
p.println();
}
p.flush();
p.close();
sendEmail(Uri.fromFile(temp));
} catch(IOException e) {
if(LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e);
}
}
}.execute();
}
private void sendEmail(Uri attachment) {
Intent i = new Intent(ACTION_SEND);
i.setType("message/rfc822");
i.putExtra(EXTRA_EMAIL, new String[] { "debug@briarproject.org" });
i.putExtra(EXTRA_SUBJECT, "Debugging information");
i.putExtra(EXTRA_STREAM, attachment);
startActivity(Intent.createChooser(i, "Send to developers"));
}
}

View File

@@ -68,6 +68,7 @@ class DroidtoothPlugin implements DuplexPlugin {
private volatile boolean running = false;
private volatile boolean wasEnabled = false, isEnabled = false;
private volatile BluetoothServerSocket socket = null;
// Non-null if running has ever been true
private volatile BluetoothAdapter adapter = null;
@@ -149,7 +150,8 @@ class DroidtoothPlugin implements DuplexPlugin {
tryToClose(ss);
return;
}
acceptContactConnections(ss);
socket = ss;
acceptContactConnections();
}
private boolean enableBluetooth() {
@@ -198,15 +200,15 @@ class DroidtoothPlugin implements DuplexPlugin {
}
}
private void acceptContactConnections(BluetoothServerSocket ss) {
private void acceptContactConnections() {
while(true) {
BluetoothSocket s;
try {
s = ss.accept();
s = socket.accept();
} catch(IOException e) {
// This is expected when the socket is closed
if(LOG.isLoggable(INFO)) LOG.log(INFO, e.toString(), e);
tryToClose(ss);
tryToClose(socket);
return;
}
callback.incomingConnectionCreated(wrapSocket(s));
@@ -220,6 +222,7 @@ class DroidtoothPlugin implements DuplexPlugin {
public void stop() {
running = false;
if(socket != null) tryToClose(socket);
// Disable Bluetooth if we enabled it at startup
if(isEnabled && !wasEnabled) disableBluetooth();
}
@@ -246,6 +249,10 @@ class DroidtoothPlugin implements DuplexPlugin {
}
}
public boolean isRunning() {
return running && socket != null;
}
public boolean shouldPoll() {
return true;
}

View File

@@ -72,7 +72,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
private final File torDirectory, torFile, geoIpFile, configFile, doneFile;
private final File cookieFile, pidFile, hostnameFile;
private volatile boolean running = false;
private volatile boolean running = false, networkEnabled = false;
private volatile Process tor = null;
private volatile int pid = -1;
private volatile ServerSocket socket = null;
@@ -509,6 +509,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
if(!running) return;
if(LOG.isLoggable(INFO)) LOG.info("Enabling network: " + enable);
controlConnection.setConf("DisableNetwork", enable ? "0" : "1");
networkEnabled = enable;
}
public void stop() throws IOException {
@@ -534,6 +535,10 @@ class TorPlugin implements DuplexPlugin, EventHandler {
}
}
public boolean isRunning() {
return running && networkEnabled;
}
public boolean shouldPoll() {
return true;
}

View File

@@ -23,6 +23,9 @@ public interface Plugin {
/** Stops the plugin. */
void stop() throws IOException;
/** Returns true if the plugin is running. */
boolean isRunning();
/**
* Returns true if the plugin's {@link #poll(Collection)} method should be
* called periodically to attempt to establish connections.

View File

@@ -2,6 +2,7 @@ package org.briarproject.api.plugins;
import java.util.Collection;
import org.briarproject.api.TransportId;
import org.briarproject.api.lifecycle.Service;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
@@ -11,6 +12,12 @@ import org.briarproject.api.plugins.duplex.DuplexPlugin;
*/
public interface PluginManager extends Service {
/**
* Returns the plugin for the given transport, or null if no such plugin
* is running.
*/
Plugin getPlugin(TransportId t);
/** Returns any running duplex plugins that support invitations. */
Collection<DuplexPlugin> getInvitationPlugins();
}

View File

@@ -9,6 +9,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@@ -56,6 +57,7 @@ class PluginManagerImpl implements PluginManager {
private final Poller poller;
private final ConnectionDispatcher dispatcher;
private final UiCallback uiCallback;
private final Map<TransportId, Plugin> plugins;
private final List<SimplexPlugin> simplexPlugins;
private final List<DuplexPlugin> duplexPlugins;
@@ -73,6 +75,7 @@ class PluginManagerImpl implements PluginManager {
this.poller = poller;
this.dispatcher = dispatcher;
this.uiCallback = uiCallback;
plugins = new ConcurrentHashMap<TransportId, Plugin>();
simplexPlugins = new CopyOnWriteArrayList<SimplexPlugin>();
duplexPlugins = new CopyOnWriteArrayList<DuplexPlugin>();
}
@@ -104,10 +107,7 @@ class PluginManagerImpl implements PluginManager {
}
// Start the poller
if(LOG.isLoggable(INFO)) LOG.info("Starting poller");
List<Plugin> plugins = new ArrayList<Plugin>();
plugins.addAll(simplexPlugins);
plugins.addAll(duplexPlugins);
poller.start(Collections.unmodifiableList(plugins));
poller.start(plugins.values());
return true;
}
@@ -115,8 +115,7 @@ class PluginManagerImpl implements PluginManager {
// Stop the poller
if(LOG.isLoggable(INFO)) LOG.info("Stopping poller");
poller.stop();
int plugins = simplexPlugins.size() + duplexPlugins.size();
final CountDownLatch latch = new CountDownLatch(plugins);
final CountDownLatch latch = new CountDownLatch(plugins.size());
// Stop the simplex plugins
if(LOG.isLoggable(INFO)) LOG.info("Stopping simplex plugins");
for(SimplexPlugin plugin : simplexPlugins)
@@ -125,6 +124,7 @@ class PluginManagerImpl implements PluginManager {
if(LOG.isLoggable(INFO)) LOG.info("Stopping duplex plugins");
for(DuplexPlugin plugin : duplexPlugins)
pluginExecutor.execute(new PluginStopper(plugin, latch));
plugins.clear();
simplexPlugins.clear();
duplexPlugins.clear();
// Wait for all the plugins to stop
@@ -139,6 +139,10 @@ class PluginManagerImpl implements PluginManager {
return true;
}
public Plugin getPlugin(TransportId t) {
return plugins.get(t);
}
public Collection<DuplexPlugin> getInvitationPlugins() {
List<DuplexPlugin> supported = new ArrayList<DuplexPlugin>();
for(DuplexPlugin d : duplexPlugins)
@@ -185,6 +189,7 @@ class PluginManagerImpl implements PluginManager {
boolean started = plugin.start();
long duration = clock.currentTimeMillis() - start;
if(started) {
plugins.put(id, plugin);
simplexPlugins.add(plugin);
if(LOG.isLoggable(INFO)) {
String name = plugin.getClass().getSimpleName();
@@ -246,6 +251,7 @@ class PluginManagerImpl implements PluginManager {
boolean started = plugin.start();
long duration = clock.currentTimeMillis() - start;
if(started) {
plugins.put(id, plugin);
duplexPlugins.add(plugin);
if(LOG.isLoggable(INFO)) {
String name = plugin.getClass().getSimpleName();

View File

@@ -55,6 +55,10 @@ public abstract class FilePlugin implements SimplexPlugin {
return maxLatency;
}
public boolean isRunning() {
return running;
}
public SimplexTransportReader createReader(ContactId c) {
return null;
}

View File

@@ -146,6 +146,10 @@ abstract class TcpPlugin implements DuplexPlugin {
if(socket != null) tryToClose(socket);
}
public boolean isRunning() {
return running && socket != null && socket.isBound();
}
public boolean shouldPoll() {
return true;
}

View File

@@ -172,6 +172,10 @@ class BluetoothPlugin implements DuplexPlugin {
tryToClose(socket);
}
public boolean isRunning() {
return running;
}
public boolean shouldPoll() {
return true;
}

View File

@@ -98,23 +98,8 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
}
}
private boolean resetModem() {
if(!running) return false;
for(String portName : serialPortList.getPortNames()) {
if(LOG.isLoggable(INFO))
LOG.info("Trying to initialise modem on " + portName);
modem = modemFactory.createModem(this, portName);
try {
if(!modem.start()) continue;
if(LOG.isLoggable(INFO))
LOG.info("Initialised modem on " + portName);
return true;
} catch(IOException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
}
running = false;
return false;
public boolean isRunning() {
return running;
}
public boolean shouldPoll() {
@@ -180,6 +165,25 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
}
}
private boolean resetModem() {
if(!running) return false;
for(String portName : serialPortList.getPortNames()) {
if(LOG.isLoggable(INFO))
LOG.info("Trying to initialise modem on " + portName);
modem = modemFactory.createModem(this, portName);
try {
if(!modem.start()) continue;
if(LOG.isLoggable(INFO))
LOG.info("Initialised modem on " + portName);
return true;
} catch(IOException e) {
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
}
running = false;
return false;
}
public DuplexTransportConnection createConnection(ContactId c) {
if(!running) return null;
// Get the ISO 3166 code for the caller's country