Commit 2f7e2e16 authored by akwizgran's avatar akwizgran

Merged changes from the afsnit repo.

The project is now built as an Android project (via Eclipse or
ant). Tests have been moved to a separate project so they can exist
outside the Android build process. A basic Android app structure has
been created. A Bluetooth plugin for Android has been added, and the
Bluetooth plugin for J2SE has been modified to use the same techniques.
parent a66da73d
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding=".gitignore|build.xml" kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="lib" path="libs/activation.jar"/>
<classpathentry kind="lib" path="libs/bluecove-2.1.0-briar.jar"/>
<classpathentry kind="lib" path="libs/bluecove-gpl-2.1.0.jar"/>
<classpathentry kind="lib" path="libs/commons-io-2.0.1.jar"/>
<classpathentry kind="lib" path="libs/guice-3.0-no_aop.jar"/>
<classpathentry kind="lib" path="libs/h2small-1.3.161.jar"/>
<classpathentry kind="lib" path="libs/javax.inject-1.jar"/>
<classpathentry kind="lib" path="libs/jna.jar"/>
<classpathentry kind="lib" path="libs/jnotify-0.93.jar"/>
<classpathentry kind="lib" path="libs/mail.jar"/>
<classpathentry kind="lib" path="libs/platform.jar"/>
<classpathentry kind="lib" path="libs/sc-light-jdk15on-20120824.jar"/>
<classpathentry kind="lib" path="libs/scprov-jdk15on-20120824.jar"/>
<classpathentry kind="lib" path="libs/silvertunnel.org_netlib.jar"/>
<classpathentry kind="lib" path="libs/test/hamcrest-core-1.1.jar"/>
<classpathentry kind="lib" path="libs/test/hamcrest-library-1.1.jar"/>
<classpathentry kind="lib" path="libs/test/jmock-2.5.1.jar"/>
<classpathentry kind="lib" path="libs/test/junit-4.9b3.jar"/>
<classpathentry kind="output" path="bin"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>
/windows-jre
/Briar
/bin
bin
gen
local.properties
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>prototype</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>prototype</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.sf.briar"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<application android:label="@string/app_name" >
<activity
android:name=".Briar"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".BriarService" android:exported="false" >
<intent-filter>
<action android:name="net.sf.briar.BriarService" />
</intent-filter>
</service>
</application>
</manifest>
File added
# This file is used to override default values used by the Ant build system.
#
# This file must be checked into Version Control Systems, as it is
# integral to the build system of your project.
# This file is only used by the Ant script.
# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.
# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.
<project name='build-common'>
<import file='dependencies.xml'/>
<dirname property='build-common.root' file='${ant.file.build-common}'/>
<fileset id='bundled-jars' dir='${build-common.root}/libs'>
<include name='*.jar'/>
</fileset>
<fileset id='test-jars' dir='${build-common.root}/libs/test'>
<include name='*.jar'/>
</fileset>
<path id='classes'>
<pathelement location='${build-common.root}/src/build'/>
</path>
<path id='test-classes'>
<pathelement location='${build-common.root}/test/build'/>
</path>
<target name='clean'>
<delete dir='build'/>
<delete dir='test.tmp'/>
</target>
<target name='compile'>
<mkdir dir='build'/>
<javac srcdir='net/sf/briar' destdir='build' source='1.5'
includeantruntime='false' debug='on'>
<classpath>
<fileset refid='bundled-jars'/>
<fileset refid='test-jars'/>
<path refid='classes'/>
</classpath>
</javac>
</target>
<target name='depend'>
<antcall target='depend.${ant.project.name}'/>
</target>
<target name='depend-clean'>
<antcall target='depend-clean.${ant.project.name}'/>
</target>
</project>
<project name='all' default='depend'>
<import file='build-common.xml'/>
<target name='doc'>
<delete dir='javadoc'/>
<javadoc destdir='javadoc' windowtitle='Briar'>
<classpath>
<fileset refid='bundled-jars'/>
</classpath>
<fileset dir='.' defaultexcludes='yes'>
<include name='src/net/sf/briar/**'/>
</fileset>
</javadoc>
</target>
<?xml version="1.0" encoding="UTF-8"?>
<project name="Briar" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
'android' tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is 'src'.
out.dir
The name of the output directory. Default is 'bin'.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the 'android'
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>
<project name='dependencies'>
<dirname property='depend.root' file='${ant.file.dependencies}'/>
<target name='depend.all' depends='depend.src'/>
<target name='depend.src'>
<ant dir='${depend.root}/src' target='compile'
inheritAll='false'/>
</target>
<target name='depend.test' depends='depend.src'>
<ant dir='${depend.root}/test' target='compile'
inheritAll='false'/>
</target>
<target name='depend-clean.all' depends='depend-clean.src'/>
<target name='depend-clean.src'>
<ant dir='${depend.root}/src' target='clean'
inheritAll='false'/>
</target>
<target name='depend-clean.test' depends='depend-clean.src'>
<ant dir='${depend.root}/test' target='clean'
inheritAll='false'/>
</target>
</project>
# To enable ProGuard in your project, edit project.properties
# to define the proguard.config property as described in that file.
#
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in ${sdk.dir}/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the ProGuard
# include property in project.properties.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-16
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Briar</string>
</resources>
<project name='api' default='depend'>
<import file='../build-common.xml'/>
<project name='prototype' default='compile'>
<fileset id='prototype-jars' dir='../libs'>
<include name='*.jar'/>
</fileset>
<path id='android-jar'>
<pathelement location='../android.jar'/>
</path>
<path id='prototype-classes'>
<pathelement location='../build'/>
</path>
<target name='clean'>
<delete dir='../build'/>
</target>
<target name='compile'>
<mkdir dir='../build'/>
<javac srcdir='net/sf/briar' destdir='../build' source='1.5'
includeantruntime='false' debug='off'>
<classpath>
<fileset refid='prototype-jars'/>
<path refid='android-jar'/>
<path refid='prototype-classes'/>
</classpath>
</javac>
</target>
</project>
package net.sf.briar;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
public class HelloWorldActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView text = new TextView(this);
text.setText("Hello world");
setContentView(text);
Intent intent = new Intent("net.sf.briar.AfsnitService");
startService(intent);
}
}
package net.sf.briar;
import static android.content.Context.MODE_PRIVATE;
import java.io.File;
import net.sf.briar.api.crypto.Password;
import net.sf.briar.api.db.DatabaseConfig;
import net.sf.briar.api.ui.UiCallback;
import android.content.Context;
import com.google.inject.AbstractModule;
public class HelloWorldModule extends AbstractModule {
private final DatabaseConfig config;
private final UiCallback callback;
public HelloWorldModule(final Context appContext) {
final Password password = new Password() {
public char[] getPassword() {
return "foo bar".toCharArray();
}
};
config = new DatabaseConfig() {
public File getDataDirectory() {
return appContext.getDir("db", MODE_PRIVATE);
}
public Password getPassword() {
return password;
}
public long getMaxSize() {
return Long.MAX_VALUE;
}
};
callback = new UiCallback() {
public int showChoice(String[] options, String... message) {
return -1;
}
public boolean showConfirmationMessage(String... message) {
return false;
}
public void showMessage(String... message) {}
};
}
@Override
protected void configure() {
bind(DatabaseConfig.class).toInstance(config);
bind(UiCallback.class).toInstance(callback);
}
}
package net.sf.briar;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.briar.android.AndroidModule;
import net.sf.briar.api.crypto.KeyManager;
import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.plugins.PluginManager;
import net.sf.briar.clock.ClockModule;
import net.sf.briar.crypto.CryptoModule;
import net.sf.briar.db.DatabaseModule;
import net.sf.briar.lifecycle.LifecycleModule;
import net.sf.briar.plugins.PluginsModule;
import net.sf.briar.protocol.ProtocolModule;
import net.sf.briar.protocol.duplex.DuplexProtocolModule;
import net.sf.briar.protocol.simplex.SimplexProtocolModule;
import net.sf.briar.serial.SerialModule;
import net.sf.briar.transport.TransportModule;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class HelloWorldService extends Service implements Runnable {
private static final Logger LOG =
Logger.getLogger(HelloWorldService.class.getName());
private DatabaseComponent db = null;
private KeyManager keyManager = null;
private PluginManager pluginManager = null;
@Override
public void onCreate() {
Thread t = new Thread(this);
t.setDaemon(false);
t.start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return 0;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void run() {
Injector i = Guice.createInjector(
new HelloWorldModule(getApplicationContext()),
new AndroidModule(), new ClockModule(), new CryptoModule(),
new DatabaseModule(), new LifecycleModule(),
new PluginsModule(), new ProtocolModule(),
new DuplexProtocolModule(), new SimplexProtocolModule(),
new SerialModule(), new TransportModule());
db = i.getInstance(DatabaseComponent.class);
keyManager = i.getInstance(KeyManager.class);
pluginManager = i.getInstance(PluginManager.class);
try {
// Start...
if(LOG.isLoggable(Level.INFO)) LOG.info("Starting");
db.open(false);
if(LOG.isLoggable(Level.INFO)) LOG.info("Database opened");
keyManager.start();
if(LOG.isLoggable(Level.INFO)) LOG.info("Key manager started");
int pluginsStarted = pluginManager.start(this);
if(LOG.isLoggable(Level.INFO))
LOG.info(pluginsStarted + " plugins started");
// ...sleep...
try {
Thread.sleep(1000);
} catch(InterruptedException ignored) {}
// ...and stop
if(LOG.isLoggable(Level.INFO)) LOG.info("Shutting down");
int pluginsStopped = pluginManager.stop();
if(LOG.isLoggable(Level.INFO))
LOG.info(pluginsStopped + " plugins stopped");
keyManager.stop();
if(LOG.isLoggable(Level.INFO)) LOG.info("Key manager stopped");
db.close();
if(LOG.isLoggable(Level.INFO)) LOG.info("Database closed");
} catch(DbException e) {
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
} catch(IOException e) {
if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
}
}
}
package net.sf.briar.android;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicBoolean;
import net.sf.briar.api.android.AndroidExecutor;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import com.google.inject.Inject;
class AndroidExecutorImpl implements AndroidExecutor {
private static final int SHUTDOWN = 0, RUNNABLE = 1, CALLABLE = 2;
private final Runnable loop;
private final AtomicBoolean started = new AtomicBoolean(false);
private final CountDownLatch startLatch = new CountDownLatch(1);
private volatile Handler handler = null;
@Inject
AndroidExecutorImpl() {
loop = new Runnable() {
public void run() {
Looper.prepare();
handler = new FutureTaskHandler();
startLatch.countDown();
Looper.loop();
}
};
}
private void startIfNecessary() {
if(started.getAndSet(true)) return;
new Thread(loop).start();
try {
startLatch.await();
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public Future<Void> submit(Runnable r) {
startIfNecessary();
Future<Void> f = new FutureTask<Void>(r, null);
Message m = Message.obtain(handler, RUNNABLE, f);
handler.sendMessage(m);
return f;
}
public <V> Future<V> submit(Callable<V> c) {
startIfNecessary();
Future<V> f = new FutureTask<V>(c);
Message m = Message.obtain(handler, RUNNABLE, f);
handler.sendMessage(m);
return f;
}
public void shutdown() {
if(handler != null) {
Message m = Message.obtain(handler, SHUTDOWN);
handler.sendMessage(m);
}
}
private static class FutureTaskHandler extends Handler {
@Override
public void handleMessage(Message m) {
switch(m.what) {
case SHUTDOWN:
Looper.myLooper().quit();
break;
case RUNNABLE:
case CALLABLE:
((FutureTask<?>) m.obj).run();
break;
default:
throw new IllegalArgumentException();
}
}
}
}
package net.sf.briar.android;
import net.sf.briar.api.android.AndroidExecutor;
import com.google.inject.AbstractModule;
public class AndroidModule extends AbstractModule {
@Override
protected void configure() {
bind(AndroidExecutor.class).to(AndroidExecutorImpl.class);
}
}
package net.sf.briar.api.android;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
/**
* Enables background threads to make Android API calls that must be made from
* a thread with a message queue.
*/
public interface AndroidExecutor {
Future<Void> submit(Runnable r);
<V> Future<V> submit(Callable<V> c);
void shutdown();
}
package net.sf.briar.api.crypto;
import net.sf.briar.api.ContactId;