From 8fffc93bbc924585f7e8d131e1c8f2fc27781619 Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Mon, 12 Nov 2012 16:39:01 +0000 Subject: [PATCH] Rewrote Android invitation wizard to use Views instead of Activities. --- AndroidManifest.xml | 30 +--- res/values/roboguice.xml | 2 +- .../helloworld/HelloWorldActivity.java | 4 +- .../invitation/AddContactActivity.java | 128 ++++++++++++++++++ .../android/invitation/AddContactView.java | 25 ++++ .../invitation/AndroidInvitationModule.java | 14 -- .../android/invitation/CodeEntryListener.java | 2 +- .../android/invitation/CodeEntryWidget.java | 20 ++- .../invitation/CodesDoNotMatchActivity.java | 69 ---------- .../invitation/CodesDoNotMatchView.java | 58 ++++++++ .../invitation/ConfirmationCodeActivity.java | 79 ----------- .../invitation/ConfirmationCodeView.java | 58 ++++++++ .../invitation/ConfirmationListener.java | 8 -- .../invitation/ConnectionActivity.java | 113 ---------------- .../invitation/ConnectionFailedActivity.java | 109 --------------- .../invitation/ConnectionFailedView.java | 86 ++++++++++++ .../invitation/ConnectionListener.java | 8 -- .../android/invitation/ConnectionView.java | 71 ++++++++++ ...dedActivity.java => ContactAddedView.java} | 59 ++++---- .../invitation/InvitationCodeActivity.java | 56 -------- .../invitation/InvitationCodeView.java | 46 +++++++ .../android/invitation/InvitationManager.java | 26 ---- .../invitation/InvitationManagerImpl.java | 67 --------- .../invitation/NetworkSetupActivity.java | 99 -------------- .../android/invitation/NetworkSetupView.java | 76 +++++++++++ .../invitation/WaitForContactActivity.java | 89 ------------ .../invitation/WaitForContactView.java | 62 +++++++++ .../sf/briar/api/crypto/CryptoComponent.java | 10 +- .../sf/briar/api/db/DatabaseComponent.java | 2 +- .../api/invitation/ConfirmationCallback.java | 14 ++ .../api/invitation/ConnectionCallback.java | 18 +++ .../api/invitation/InvitationManager.java | 17 +++ .../api/plugins/InvitationConstants.java | 6 +- src/net/sf/briar/api/plugins/Plugin.java | 6 +- .../sf/briar/api/plugins/PluginCallback.java | 2 +- .../sf/briar/api/plugins/PluginManager.java | 4 + .../simplex/SimplexTransportReader.java | 3 +- .../simplex/SimplexTransportWriter.java | 3 +- src/net/sf/briar/api/ui/UiCallback.java | 2 +- .../sf/briar/crypto/CryptoComponentImpl.java | 4 +- src/net/sf/briar/crypto/PseudoRandomImpl.java | 7 +- src/net/sf/briar/db/Database.java | 8 +- .../sf/briar/db/DatabaseComponentImpl.java | 4 +- .../invitation/InvitationManagerImpl.java | 81 +++++++++++ .../sf/briar/invitation/InvitationModule.java | 13 ++ .../sf/briar/plugins/PluginManagerImpl.java | 9 ++ .../plugins/droidtooth/DroidtoothPlugin.java | 8 +- .../briar/transport/ConnectionWriterImpl.java | 2 +- 48 files changed, 843 insertions(+), 844 deletions(-) create mode 100644 src/net/sf/briar/android/invitation/AddContactActivity.java create mode 100644 src/net/sf/briar/android/invitation/AddContactView.java delete mode 100644 src/net/sf/briar/android/invitation/AndroidInvitationModule.java delete mode 100644 src/net/sf/briar/android/invitation/CodesDoNotMatchActivity.java create mode 100644 src/net/sf/briar/android/invitation/CodesDoNotMatchView.java delete mode 100644 src/net/sf/briar/android/invitation/ConfirmationCodeActivity.java create mode 100644 src/net/sf/briar/android/invitation/ConfirmationCodeView.java delete mode 100644 src/net/sf/briar/android/invitation/ConfirmationListener.java delete mode 100644 src/net/sf/briar/android/invitation/ConnectionActivity.java delete mode 100644 src/net/sf/briar/android/invitation/ConnectionFailedActivity.java create mode 100644 src/net/sf/briar/android/invitation/ConnectionFailedView.java delete mode 100644 src/net/sf/briar/android/invitation/ConnectionListener.java create mode 100644 src/net/sf/briar/android/invitation/ConnectionView.java rename src/net/sf/briar/android/invitation/{ContactAddedActivity.java => ContactAddedView.java} (56%) delete mode 100644 src/net/sf/briar/android/invitation/InvitationCodeActivity.java create mode 100644 src/net/sf/briar/android/invitation/InvitationCodeView.java delete mode 100644 src/net/sf/briar/android/invitation/InvitationManager.java delete mode 100644 src/net/sf/briar/android/invitation/InvitationManagerImpl.java delete mode 100644 src/net/sf/briar/android/invitation/NetworkSetupActivity.java create mode 100644 src/net/sf/briar/android/invitation/NetworkSetupView.java delete mode 100644 src/net/sf/briar/android/invitation/WaitForContactActivity.java create mode 100644 src/net/sf/briar/android/invitation/WaitForContactView.java create mode 100644 src/net/sf/briar/api/invitation/ConfirmationCallback.java create mode 100644 src/net/sf/briar/api/invitation/ConnectionCallback.java create mode 100644 src/net/sf/briar/api/invitation/InvitationManager.java create mode 100644 src/net/sf/briar/invitation/InvitationManagerImpl.java create mode 100644 src/net/sf/briar/invitation/InvitationModule.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index f58b344443..a81aeebad8 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -32,35 +32,7 @@ </intent-filter> </activity> <activity - android:name=".android.invitation.NetworkSetupActivity" - android:label="@string/add_a_contact" > - </activity> - <activity - android:name=".android.invitation.InvitationCodeActivity" - android:label="@string/add_a_contact" > - </activity> - <activity - android:name=".android.invitation.ConnectionActivity" - android:label="@string/add_a_contact" > - </activity> - <activity - android:name=".android.invitation.ConnectionFailedActivity" - android:label="@string/add_a_contact" > - </activity> - <activity - android:name=".android.invitation.ConfirmationCodeActivity" - android:label="@string/add_a_contact" > - </activity> - <activity - android:name=".android.invitation.WaitForContactActivity" - android:label="@string/add_a_contact" > - </activity> - <activity - android:name=".android.invitation.CodesDoNotMatchActivity" - android:label="@string/add_a_contact" > - </activity> - <activity - android:name=".android.invitation.ContactAddedActivity" + android:name=".android.invitation.AddContactActivity" android:label="@string/add_a_contact" > </activity> </application> diff --git a/res/values/roboguice.xml b/res/values/roboguice.xml index 82fd88cbc5..a20130d0f1 100644 --- a/res/values/roboguice.xml +++ b/res/values/roboguice.xml @@ -3,10 +3,10 @@ <string-array name="roboguice_modules"> <item>net.sf.briar.android.AndroidModule</item> <item>net.sf.briar.android.helloworld.HelloWorldModule</item> - <item>net.sf.briar.android.invitation.AndroidInvitationModule</item> <item>net.sf.briar.clock.ClockModule</item> <item>net.sf.briar.crypto.CryptoModule</item> <item>net.sf.briar.db.DatabaseModule</item> + <item>net.sf.briar.invitation.InvitationModule</item> <item>net.sf.briar.lifecycle.LifecycleModule</item> <item>net.sf.briar.plugins.PluginsModule</item> <item>net.sf.briar.protocol.ProtocolModule</item> diff --git a/src/net/sf/briar/android/helloworld/HelloWorldActivity.java b/src/net/sf/briar/android/helloworld/HelloWorldActivity.java index 794495d24d..98f9e52d5c 100644 --- a/src/net/sf/briar/android/helloworld/HelloWorldActivity.java +++ b/src/net/sf/briar/android/helloworld/HelloWorldActivity.java @@ -9,7 +9,7 @@ import static java.util.logging.Level.INFO; import java.util.logging.Logger; import net.sf.briar.R; -import net.sf.briar.android.invitation.NetworkSetupActivity; +import net.sf.briar.android.invitation.AddContactActivity; import roboguice.activity.RoboActivity; import android.content.Intent; import android.os.Bundle; @@ -66,6 +66,6 @@ implements OnClickListener { } public void onClick(View view) { - startActivity(new Intent(this, NetworkSetupActivity.class)); + startActivity(new Intent(this, AddContactActivity.class)); } } diff --git a/src/net/sf/briar/android/invitation/AddContactActivity.java b/src/net/sf/briar/android/invitation/AddContactActivity.java new file mode 100644 index 0000000000..20c7cdd63f --- /dev/null +++ b/src/net/sf/briar/android/invitation/AddContactActivity.java @@ -0,0 +1,128 @@ +package net.sf.briar.android.invitation; + +import net.sf.briar.api.crypto.CryptoComponent; +import net.sf.briar.api.invitation.ConfirmationCallback; +import net.sf.briar.api.invitation.ConnectionCallback; +import net.sf.briar.api.invitation.InvitationManager; +import roboguice.activity.RoboActivity; + +import com.google.inject.Inject; + +public class AddContactActivity extends RoboActivity +implements ConnectionCallback, ConfirmationCallback { + + @Inject private CryptoComponent crypto; + @Inject private InvitationManager invitationManager; + + // All of the following must be accessed on the UI thread + private AddContactView view = null; + private String networkName = null; + private boolean useBluetooth = false; + private int localInvitationCode = -1; + private int localConfirmationCode = -1, remoteConfirmationCode = -1; + private ConfirmationCallback callback = null; + private boolean localMatched = false; + private boolean remoteCompared = false, remoteMatched = false; + + @Override + public void onResume() { + super.onResume(); + if(view == null) setView(new NetworkSetupView(this)); + else view.populate(); + } + + void setView(AddContactView view) { + this.view = view; + view.init(this); + setContentView(view); + } + + void setNetworkName(String networkName) { + this.networkName = networkName; + } + + String getNetworkName() { + return networkName; + } + + void setUseBluetooth(boolean useBluetooth) { + this.useBluetooth = useBluetooth; + } + + boolean getUseBluetooth() { + return useBluetooth; + } + + int generateLocalInvitationCode() { + localInvitationCode = crypto.generateInvitationCode(); + return localInvitationCode; + } + + int getLocalInvitationCode() { + return localInvitationCode; + } + + void remoteInvitationCodeEntered(int code) { + setView(new ConnectionView(this)); + localMatched = remoteCompared = remoteMatched = false; + invitationManager.connect(localInvitationCode, code, this); + } + + int getLocalConfirmationCode() { + return localConfirmationCode; + } + + void remoteConfirmationCodeEntered(int code) { + if(code == remoteConfirmationCode) { + localMatched = true; + if(remoteMatched) setView(new ContactAddedView(this)); + else if(remoteCompared) setView(new CodesDoNotMatchView(this)); + else setView(new WaitForContactView(this)); + callback.codesMatch(); + } else { + setView(new CodesDoNotMatchView(this)); + callback.codesDoNotMatch(); + } + } + + public void connectionEstablished(final int localCode, final int remoteCode, + final ConfirmationCallback c) { + runOnUiThread(new Runnable() { + public void run() { + localConfirmationCode = localCode; + remoteConfirmationCode = remoteCode; + callback = c; + setView(new ConfirmationCodeView(AddContactActivity.this)); + } + }); + } + + public void connectionNotEstablished() { + runOnUiThread(new Runnable() { + public void run() { + setView(new ConnectionFailedView(AddContactActivity.this)); + } + }); + } + + public void codesMatch() { + runOnUiThread(new Runnable() { + public void run() { + remoteCompared = true; + remoteMatched = true; + if(localMatched) + setView(new ContactAddedView(AddContactActivity.this)); + } + }); + } + + public void codesDoNotMatch() { + runOnUiThread(new Runnable() { + public void run() { + remoteCompared = true; + if(localMatched) + setView(new CodesDoNotMatchView(AddContactActivity.this)); + } + }); + } +} diff --git a/src/net/sf/briar/android/invitation/AddContactView.java b/src/net/sf/briar/android/invitation/AddContactView.java new file mode 100644 index 0000000000..cd90bc0fd8 --- /dev/null +++ b/src/net/sf/briar/android/invitation/AddContactView.java @@ -0,0 +1,25 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER_HORIZONTAL; +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import android.content.Context; +import android.widget.LinearLayout; + +abstract class AddContactView extends LinearLayout { + + protected AddContactActivity container = null; + + AddContactView(Context context) { + super(context); + } + + void init(AddContactActivity container) { + this.container = container; + setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); + setOrientation(VERTICAL); + setGravity(CENTER_HORIZONTAL); + populate(); + } + + abstract void populate(); +} diff --git a/src/net/sf/briar/android/invitation/AndroidInvitationModule.java b/src/net/sf/briar/android/invitation/AndroidInvitationModule.java deleted file mode 100644 index c917e2256b..0000000000 --- a/src/net/sf/briar/android/invitation/AndroidInvitationModule.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.sf.briar.android.invitation; - -import javax.inject.Singleton; - -import com.google.inject.AbstractModule; - -public class AndroidInvitationModule extends AbstractModule { - - @Override - protected void configure() { - bind(InvitationManager.class).to(InvitationManagerImpl.class).in( - Singleton.class); - } -} diff --git a/src/net/sf/briar/android/invitation/CodeEntryListener.java b/src/net/sf/briar/android/invitation/CodeEntryListener.java index 1a8f7b3d8d..43c3245644 100644 --- a/src/net/sf/briar/android/invitation/CodeEntryListener.java +++ b/src/net/sf/briar/android/invitation/CodeEntryListener.java @@ -2,5 +2,5 @@ package net.sf.briar.android.invitation; interface CodeEntryListener { - void codeEntered(String code); + void codeEntered(int remoteCode); } diff --git a/src/net/sf/briar/android/invitation/CodeEntryWidget.java b/src/net/sf/briar/android/invitation/CodeEntryWidget.java index 788e23b85a..5f129481b5 100644 --- a/src/net/sf/briar/android/invitation/CodeEntryWidget.java +++ b/src/net/sf/briar/android/invitation/CodeEntryWidget.java @@ -3,6 +3,7 @@ package net.sf.briar.android.invitation; import static android.text.InputType.TYPE_CLASS_NUMBER; import static android.view.Gravity.CENTER; import static android.view.Gravity.CENTER_HORIZONTAL; +import static net.sf.briar.api.plugins.InvitationConstants.MAX_CODE; import net.sf.briar.R; import android.content.Context; import android.view.KeyEvent; @@ -53,6 +54,7 @@ OnEditorActionListener, OnClickListener { codeEntry.setMaxEms(5); codeEntry.setMaxLines(1); codeEntry.setInputType(TYPE_CLASS_NUMBER); + codeEntry.requestFocus(); LinearLayout innerLayout = new LinearLayout(ctx); innerLayout.setOrientation(HORIZONTAL); @@ -63,16 +65,24 @@ OnEditorActionListener, OnClickListener { } public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) { - validateAndReturnCode(); + if(!validateAndReturnCode()) codeEntry.setText(""); return true; } public void onClick(View view) { - validateAndReturnCode(); + if(!validateAndReturnCode()) codeEntry.setText(""); } - private void validateAndReturnCode() { - CharSequence code = codeEntry.getText(); - if(code.length() == 6) listener.codeEntered(code.toString()); + private boolean validateAndReturnCode() { + String remoteCodeString = codeEntry.getText().toString(); + int remoteCode; + try { + remoteCode = Integer.valueOf(remoteCodeString); + } catch(NumberFormatException e) { + return false; + } + if(remoteCode < 0 || remoteCode > MAX_CODE) return false; + listener.codeEntered(remoteCode); + return true; } } diff --git a/src/net/sf/briar/android/invitation/CodesDoNotMatchActivity.java b/src/net/sf/briar/android/invitation/CodesDoNotMatchActivity.java deleted file mode 100644 index 861a80c700..0000000000 --- a/src/net/sf/briar/android/invitation/CodesDoNotMatchActivity.java +++ /dev/null @@ -1,69 +0,0 @@ -package net.sf.briar.android.invitation; - -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; -import static android.widget.LinearLayout.HORIZONTAL; -import static android.widget.LinearLayout.VERTICAL; -import net.sf.briar.R; -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup.LayoutParams; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -public class CodesDoNotMatchActivity extends Activity -implements OnClickListener { - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); - layout.setOrientation(VERTICAL); - layout.setGravity(CENTER_HORIZONTAL); - - LinearLayout innerLayout = new LinearLayout(this); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ImageView icon = new ImageView(this); - icon.setPadding(10, 10, 10, 10); - icon.setImageResource(R.drawable.alerts_and_states_error); - innerLayout.addView(icon); - - TextView failed = new TextView(this); - failed.setTextSize(20); - failed.setText(R.string.codes_do_not_match); - innerLayout.addView(failed); - layout.addView(innerLayout); - - TextView interfering = new TextView(this); - interfering.setGravity(CENTER_HORIZONTAL); - interfering.setPadding(0, 0, 0, 10); - interfering.setText(R.string.interfering); - layout.addView(interfering); - - Button tryAgain = new Button(this); - LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT); - tryAgain.setLayoutParams(lp); - tryAgain.setText(R.string.try_again_button); - tryAgain.setOnClickListener(this); - layout.addView(tryAgain); - - setContentView(layout); - } - - public void onClick(View view) { - Intent intent = new Intent(this, InvitationCodeActivity.class); - intent.putExtras(getIntent().getExtras()); - startActivity(intent); - finish(); - } -} diff --git a/src/net/sf/briar/android/invitation/CodesDoNotMatchView.java b/src/net/sf/briar/android/invitation/CodesDoNotMatchView.java new file mode 100644 index 0000000000..d801d01ae9 --- /dev/null +++ b/src/net/sf/briar/android/invitation/CodesDoNotMatchView.java @@ -0,0 +1,58 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER; +import static android.view.Gravity.CENTER_HORIZONTAL; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import net.sf.briar.R; +import android.content.Context; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class CodesDoNotMatchView extends AddContactView +implements OnClickListener { + + CodesDoNotMatchView(Context ctx) { + super(ctx); + } + + void populate() { + removeAllViews(); + Context ctx = getContext(); + LinearLayout innerLayout = new LinearLayout(ctx); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + + ImageView icon = new ImageView(ctx); + icon.setPadding(10, 10, 10, 10); + icon.setImageResource(R.drawable.alerts_and_states_error); + innerLayout.addView(icon); + + TextView failed = new TextView(ctx); + failed.setTextSize(20); + failed.setText(R.string.codes_do_not_match); + innerLayout.addView(failed); + addView(innerLayout); + + TextView interfering = new TextView(ctx); + interfering.setGravity(CENTER_HORIZONTAL); + interfering.setPadding(0, 0, 0, 10); + interfering.setText(R.string.interfering); + addView(interfering); + + Button tryAgain = new Button(ctx); + LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT); + tryAgain.setLayoutParams(lp); + tryAgain.setText(R.string.try_again_button); + tryAgain.setOnClickListener(this); + addView(tryAgain); + } + + public void onClick(View view) { + // Try again + container.setView(new NetworkSetupView(container)); + } +} diff --git a/src/net/sf/briar/android/invitation/ConfirmationCodeActivity.java b/src/net/sf/briar/android/invitation/ConfirmationCodeActivity.java deleted file mode 100644 index 220548b580..0000000000 --- a/src/net/sf/briar/android/invitation/ConfirmationCodeActivity.java +++ /dev/null @@ -1,79 +0,0 @@ -package net.sf.briar.android.invitation; - -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.widget.LinearLayout.HORIZONTAL; -import static android.widget.LinearLayout.VERTICAL; -import net.sf.briar.R; -import roboguice.activity.RoboActivity; -import android.content.Intent; -import android.content.res.Resources; -import android.os.Bundle; -import android.view.ViewGroup.LayoutParams; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.google.inject.Inject; - -public class ConfirmationCodeActivity extends RoboActivity -implements CodeEntryListener { - - @Inject private InvitationManager manager; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); - layout.setOrientation(VERTICAL); - layout.setGravity(CENTER_HORIZONTAL); - - LinearLayout innerLayout = new LinearLayout(this); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ImageView icon = new ImageView(this); - icon.setPadding(10, 10, 10, 10); - icon.setImageResource(R.drawable.navigation_accept); - innerLayout.addView(icon); - - TextView connected = new TextView(this); - connected.setTextSize(20); - connected.setText(R.string.connected_to_contact); - innerLayout.addView(connected); - layout.addView(innerLayout); - - TextView yourCode = new TextView(this); - yourCode.setGravity(CENTER_HORIZONTAL); - yourCode.setText(R.string.your_confirmation_code); - layout.addView(yourCode); - - TextView code = new TextView(this); - code.setGravity(CENTER_HORIZONTAL); - code.setTextSize(50); - code.setText(manager.getLocalConfirmationCode()); - layout.addView(code); - - CodeEntryWidget codeEntry = new CodeEntryWidget(this); - Resources res = getResources(); - codeEntry.init(this, res.getString(R.string.enter_confirmation_code)); - layout.addView(codeEntry); - - setContentView(layout); - } - - public void codeEntered(String code) { - if(code.equals(manager.getRemoteConfirmationCode())) { - Intent intent = new Intent(this, WaitForContactActivity.class); - intent.putExtras(getIntent().getExtras()); - startActivity(intent); - } else { - Intent intent = new Intent(this, CodesDoNotMatchActivity.class); - intent.putExtras(getIntent().getExtras()); - startActivity(intent); - } - finish(); - } -} diff --git a/src/net/sf/briar/android/invitation/ConfirmationCodeView.java b/src/net/sf/briar/android/invitation/ConfirmationCodeView.java new file mode 100644 index 0000000000..04688795f9 --- /dev/null +++ b/src/net/sf/briar/android/invitation/ConfirmationCodeView.java @@ -0,0 +1,58 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER; +import static android.view.Gravity.CENTER_HORIZONTAL; +import net.sf.briar.R; +import android.content.Context; +import android.content.res.Resources; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class ConfirmationCodeView extends AddContactView +implements CodeEntryListener { + + ConfirmationCodeView(Context ctx) { + super(ctx); + } + + void populate() { + removeAllViews(); + Context ctx = getContext(); + LinearLayout innerLayout = new LinearLayout(ctx); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + + ImageView icon = new ImageView(ctx); + icon.setPadding(10, 10, 10, 10); + icon.setImageResource(R.drawable.navigation_accept); + innerLayout.addView(icon); + + TextView connected = new TextView(ctx); + connected.setTextSize(20); + connected.setText(R.string.connected_to_contact); + innerLayout.addView(connected); + addView(innerLayout); + + TextView yourCode = new TextView(ctx); + yourCode.setGravity(CENTER_HORIZONTAL); + yourCode.setText(R.string.your_confirmation_code); + addView(yourCode); + + TextView code = new TextView(ctx); + code.setGravity(CENTER_HORIZONTAL); + code.setTextSize(50); + int localCode = container.getLocalConfirmationCode(); + code.setText(String.format("%06d", localCode)); + addView(code); + + CodeEntryWidget codeEntry = new CodeEntryWidget(ctx); + Resources res = getResources(); + codeEntry.init(this, res.getString(R.string.enter_confirmation_code)); + addView(codeEntry); + } + + public void codeEntered(int remoteCode) { + container.remoteConfirmationCodeEntered(remoteCode); + } +} diff --git a/src/net/sf/briar/android/invitation/ConfirmationListener.java b/src/net/sf/briar/android/invitation/ConfirmationListener.java deleted file mode 100644 index af2024676a..0000000000 --- a/src/net/sf/briar/android/invitation/ConfirmationListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package net.sf.briar.android.invitation; - -interface ConfirmationListener { - - void confirmationReceived(); - - void confirmationNotReceived(); -} diff --git a/src/net/sf/briar/android/invitation/ConnectionActivity.java b/src/net/sf/briar/android/invitation/ConnectionActivity.java deleted file mode 100644 index 5ed8b80d38..0000000000 --- a/src/net/sf/briar/android/invitation/ConnectionActivity.java +++ /dev/null @@ -1,113 +0,0 @@ -package net.sf.briar.android.invitation; - -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.widget.LinearLayout.HORIZONTAL; -import static android.widget.LinearLayout.VERTICAL; -import net.sf.briar.R; -import roboguice.activity.RoboActivity; -import android.content.Intent; -import android.content.res.Resources; -import android.os.Bundle; -import android.view.ViewGroup.LayoutParams; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.TextView; - -import com.google.inject.Inject; - -public class ConnectionActivity extends RoboActivity -implements ConnectionListener { - - @Inject private InvitationManager manager; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); - layout.setOrientation(VERTICAL); - layout.setGravity(CENTER_HORIZONTAL); - - Bundle b = getIntent().getExtras(); - String networkName = b.getString( - "net.sf.briar.android.invitation.NETWORK_NAME"); - boolean useBluetooth = b.getBoolean( - "net.sf.briar.android.invitation.USE_BLUETOOTH"); - - TextView yourCode = new TextView(this); - yourCode.setGravity(CENTER_HORIZONTAL); - yourCode.setText(R.string.your_invitation_code); - layout.addView(yourCode); - - TextView code = new TextView(this); - code.setGravity(CENTER_HORIZONTAL); - code.setTextSize(50); - code.setText(manager.getLocalInvitationCode()); - layout.addView(code); - - if(networkName != null) { - LinearLayout innerLayout = new LinearLayout(this); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ProgressBar progress = new ProgressBar(this); - progress.setIndeterminate(true); - progress.setPadding(0, 10, 10, 0); - innerLayout.addView(progress); - - TextView connecting = new TextView(this); - Resources res = getResources(); - String connectingVia = res.getString(R.string.connecting_wifi); - connecting.setText(String.format(connectingVia, networkName)); - innerLayout.addView(connecting); - - layout.addView(innerLayout); - manager.startWifiConnectionWorker(this); - } - - if(useBluetooth) { - LinearLayout innerLayout = new LinearLayout(this); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ProgressBar progress = new ProgressBar(this); - progress.setPadding(0, 10, 10, 0); - progress.setIndeterminate(true); - innerLayout.addView(progress); - - TextView connecting = new TextView(this); - connecting.setText(R.string.connecting_bluetooth); - innerLayout.addView(connecting); - - layout.addView(innerLayout); - manager.startBluetoothConnectionWorker(this); - } - - setContentView(layout); - - manager.tryToConnect(this); - } - - public void connectionEstablished() { - final Intent intent = new Intent(this, ConfirmationCodeActivity.class); - intent.putExtras(getIntent().getExtras()); - runOnUiThread(new Runnable() { - public void run() { - startActivity(intent); - finish(); - } - }); - } - - public void connectionNotEstablished() { - final Intent intent = new Intent(this, ConnectionFailedActivity.class); - runOnUiThread(new Runnable() { - public void run() { - startActivity(intent); - finish(); - } - }); - } -} diff --git a/src/net/sf/briar/android/invitation/ConnectionFailedActivity.java b/src/net/sf/briar/android/invitation/ConnectionFailedActivity.java deleted file mode 100644 index a18e90a199..0000000000 --- a/src/net/sf/briar/android/invitation/ConnectionFailedActivity.java +++ /dev/null @@ -1,109 +0,0 @@ -package net.sf.briar.android.invitation; - -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; -import static android.widget.LinearLayout.HORIZONTAL; -import static android.widget.LinearLayout.VERTICAL; -import net.sf.briar.R; -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup.LayoutParams; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -public class ConnectionFailedActivity extends Activity -implements WifiStateListener, BluetoothStateListener, OnClickListener { - - private WifiWidget wifi = null; - private BluetoothWidget bluetooth = null; - private Button tryAgainButton = null; - private String networkName = null; - private boolean useBluetooth = false; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); - layout.setOrientation(VERTICAL); - layout.setGravity(CENTER_HORIZONTAL); - - LinearLayout innerLayout = new LinearLayout(this); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ImageView icon = new ImageView(this); - icon.setPadding(10, 10, 10, 10); - icon.setImageResource(R.drawable.alerts_and_states_error); - innerLayout.addView(icon); - - TextView failed = new TextView(this); - failed.setTextSize(20); - failed.setText(R.string.connection_failed); - innerLayout.addView(failed); - layout.addView(innerLayout); - - TextView checkNetwork = new TextView(this); - checkNetwork.setGravity(CENTER_HORIZONTAL); - checkNetwork.setText(R.string.check_same_network); - layout.addView(checkNetwork); - - wifi = new WifiWidget(this); - wifi.init(this); - layout.addView(wifi); - - bluetooth = new BluetoothWidget(this); - bluetooth.init(this); - layout.addView(bluetooth); - - tryAgainButton = new Button(this); - LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT); - tryAgainButton.setLayoutParams(lp); - tryAgainButton.setText(R.string.try_again_button); - tryAgainButton.setOnClickListener(this); - enabledOrDisableTryAgainButton(); - layout.addView(tryAgainButton); - - setContentView(layout); - } - - @Override - public void onResume() { - super.onResume(); - wifi.populate(); - bluetooth.populate(); - } - - public void wifiStateChanged(String networkName) { - this.networkName = networkName; - enabledOrDisableTryAgainButton(); - } - - public void bluetoothStateChanged(boolean enabled) { - useBluetooth = enabled; - enabledOrDisableTryAgainButton(); - } - - private void enabledOrDisableTryAgainButton() { - if(tryAgainButton == null) return; // Activity not created yet - if(useBluetooth || networkName != null) tryAgainButton.setEnabled(true); - else tryAgainButton.setEnabled(false); - } - - public void onClick(View view) { - Intent intent = new Intent(this, InvitationCodeActivity.class); - intent.putExtra("net.sf.briar.android.invitation.NETWORK_NAME", - networkName); - intent.putExtra("net.sf.briar.android.invitation.USE_BLUETOOTH", - useBluetooth); - startActivity(intent); - finish(); - } -} diff --git a/src/net/sf/briar/android/invitation/ConnectionFailedView.java b/src/net/sf/briar/android/invitation/ConnectionFailedView.java new file mode 100644 index 0000000000..970314cd94 --- /dev/null +++ b/src/net/sf/briar/android/invitation/ConnectionFailedView.java @@ -0,0 +1,86 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER; +import static android.view.Gravity.CENTER_HORIZONTAL; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import net.sf.briar.R; +import android.content.Context; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class ConnectionFailedView extends AddContactView +implements WifiStateListener, BluetoothStateListener, OnClickListener { + + private Button tryAgainButton = null; + + ConnectionFailedView(Context ctx) { + super(ctx); + } + + void populate() { + removeAllViews(); + Context ctx = getContext(); + LinearLayout innerLayout = new LinearLayout(ctx); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + + ImageView icon = new ImageView(ctx); + icon.setPadding(10, 10, 10, 10); + icon.setImageResource(R.drawable.alerts_and_states_error); + innerLayout.addView(icon); + + TextView failed = new TextView(ctx); + failed.setTextSize(20); + failed.setText(R.string.connection_failed); + innerLayout.addView(failed); + addView(innerLayout); + + TextView checkNetwork = new TextView(ctx); + checkNetwork.setGravity(CENTER_HORIZONTAL); + checkNetwork.setText(R.string.check_same_network); + addView(checkNetwork); + + WifiWidget wifi = new WifiWidget(ctx); + wifi.init(this); + addView(wifi); + + BluetoothWidget bluetooth = new BluetoothWidget(ctx); + bluetooth.init(this); + addView(bluetooth); + + tryAgainButton = new Button(ctx); + LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT); + tryAgainButton.setLayoutParams(lp); + tryAgainButton.setText(R.string.try_again_button); + tryAgainButton.setOnClickListener(this); + enabledOrDisableTryAgainButton(); + addView(tryAgainButton); + } + + public void wifiStateChanged(String networkName) { + container.setNetworkName(networkName); + enabledOrDisableTryAgainButton(); + } + + public void bluetoothStateChanged(boolean enabled) { + container.setUseBluetooth(enabled); + enabledOrDisableTryAgainButton(); + } + + private void enabledOrDisableTryAgainButton() { + if(tryAgainButton == null) return; // Activity not created yet + boolean useBluetooth = container.getUseBluetooth(); + String networkName = container.getNetworkName(); + if(useBluetooth || networkName != null) tryAgainButton.setEnabled(true); + else tryAgainButton.setEnabled(false); + } + + public void onClick(View view) { + // Try again + container.setView(new InvitationCodeView(container)); + } +} diff --git a/src/net/sf/briar/android/invitation/ConnectionListener.java b/src/net/sf/briar/android/invitation/ConnectionListener.java deleted file mode 100644 index a1bc643dc3..0000000000 --- a/src/net/sf/briar/android/invitation/ConnectionListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package net.sf.briar.android.invitation; - -interface ConnectionListener { - - void connectionEstablished(); - - void connectionNotEstablished(); -} diff --git a/src/net/sf/briar/android/invitation/ConnectionView.java b/src/net/sf/briar/android/invitation/ConnectionView.java new file mode 100644 index 0000000000..5a35c26d61 --- /dev/null +++ b/src/net/sf/briar/android/invitation/ConnectionView.java @@ -0,0 +1,71 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER; +import static android.view.Gravity.CENTER_HORIZONTAL; +import net.sf.briar.R; +import android.content.Context; +import android.content.res.Resources; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +public class ConnectionView extends AddContactView { + + ConnectionView(Context ctx) { + super(ctx); + } + + void populate() { + removeAllViews(); + Context ctx = getContext(); + TextView yourCode = new TextView(ctx); + yourCode.setGravity(CENTER_HORIZONTAL); + yourCode.setText(R.string.your_invitation_code); + addView(yourCode); + + TextView code = new TextView(ctx); + code.setGravity(CENTER_HORIZONTAL); + code.setTextSize(50); + int localCode = container.getLocalInvitationCode(); + code.setText(String.format("%06d", localCode)); + addView(code); + + String networkName = container.getNetworkName(); + if(networkName != null) { + LinearLayout innerLayout = new LinearLayout(ctx); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + + ProgressBar progress = new ProgressBar(ctx); + progress.setIndeterminate(true); + progress.setPadding(0, 10, 10, 0); + innerLayout.addView(progress); + + TextView connecting = new TextView(ctx); + Resources res = getResources(); + String connectingVia = res.getString(R.string.connecting_wifi); + connecting.setText(String.format(connectingVia, networkName)); + innerLayout.addView(connecting); + + addView(innerLayout); + } + + boolean useBluetooth = container.getUseBluetooth(); + if(useBluetooth) { + LinearLayout innerLayout = new LinearLayout(ctx); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + + ProgressBar progress = new ProgressBar(ctx); + progress.setPadding(0, 10, 10, 0); + progress.setIndeterminate(true); + innerLayout.addView(progress); + + TextView connecting = new TextView(ctx); + connecting.setText(R.string.connecting_bluetooth); + innerLayout.addView(connecting); + + addView(innerLayout); + } + } +} diff --git a/src/net/sf/briar/android/invitation/ContactAddedActivity.java b/src/net/sf/briar/android/invitation/ContactAddedView.java similarity index 56% rename from src/net/sf/briar/android/invitation/ContactAddedActivity.java rename to src/net/sf/briar/android/invitation/ContactAddedView.java index 8f75032806..25ad3a3ab8 100644 --- a/src/net/sf/briar/android/invitation/ContactAddedActivity.java +++ b/src/net/sf/briar/android/invitation/ContactAddedView.java @@ -2,17 +2,11 @@ package net.sf.briar.android.invitation; import static android.view.Gravity.CENTER; import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.widget.LinearLayout.HORIZONTAL; -import static android.widget.LinearLayout.VERTICAL; import net.sf.briar.R; -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; +import android.content.Context; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; -import android.view.ViewGroup.LayoutParams; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; @@ -20,43 +14,42 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; -public class ContactAddedActivity extends Activity implements OnClickListener, +public class ContactAddedView extends AddContactView implements OnClickListener, OnEditorActionListener { - private volatile Button done = null; + private Button done = null; - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); - layout.setOrientation(VERTICAL); - layout.setGravity(CENTER_HORIZONTAL); + ContactAddedView(Context ctx) { + super(ctx); + } - LinearLayout innerLayout = new LinearLayout(this); + void populate() { + removeAllViews(); + Context ctx = getContext(); + LinearLayout innerLayout = new LinearLayout(ctx); innerLayout.setOrientation(HORIZONTAL); innerLayout.setGravity(CENTER); - ImageView icon = new ImageView(this); + ImageView icon = new ImageView(ctx); icon.setImageResource(R.drawable.navigation_accept); icon.setPadding(10, 10, 10, 10); innerLayout.addView(icon); - TextView failed = new TextView(this); + TextView failed = new TextView(ctx); failed.setText(R.string.contact_added); failed.setTextSize(20); innerLayout.addView(failed); - layout.addView(innerLayout); + addView(innerLayout); - TextView enterNickname = new TextView(this); + TextView enterNickname = new TextView(ctx); enterNickname.setGravity(CENTER_HORIZONTAL); enterNickname.setText(R.string.enter_nickname); - layout.addView(enterNickname); + addView(enterNickname); - final Button addAnother = new Button(this); - final Button done = new Button(this); + final Button addAnother = new Button(ctx); + final Button done = new Button(ctx); this.done = done; - EditText nicknameEntry = new EditText(this) { + EditText nicknameEntry = new EditText(ctx) { @Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { @@ -68,9 +61,9 @@ OnEditorActionListener { nicknameEntry.setMaxEms(20); nicknameEntry.setMaxLines(1); nicknameEntry.setOnEditorActionListener(this); - layout.addView(nicknameEntry); + addView(nicknameEntry); - innerLayout = new LinearLayout(this); + innerLayout = new LinearLayout(ctx); innerLayout.setOrientation(HORIZONTAL); innerLayout.setGravity(CENTER); @@ -83,20 +76,16 @@ OnEditorActionListener { done.setEnabled(false); done.setOnClickListener(this); innerLayout.addView(done); - layout.addView(innerLayout); - - setContentView(layout); + addView(innerLayout); } public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) { - if(textView.getText().length() > 0) finish(); + if(textView.getText().length() > 0) container.finish(); return true; } public void onClick(View view) { - if(done == null) return; - if(view != done) - startActivity(new Intent(this, NetworkSetupActivity.class)); - finish(); + if(view == done) container.finish(); // Done + else container.setView(new NetworkSetupView(container)); // Add another } } diff --git a/src/net/sf/briar/android/invitation/InvitationCodeActivity.java b/src/net/sf/briar/android/invitation/InvitationCodeActivity.java deleted file mode 100644 index 8f3bb1b41b..0000000000 --- a/src/net/sf/briar/android/invitation/InvitationCodeActivity.java +++ /dev/null @@ -1,56 +0,0 @@ -package net.sf.briar.android.invitation; - -import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.widget.LinearLayout.VERTICAL; -import net.sf.briar.R; -import roboguice.activity.RoboActivity; -import android.content.Intent; -import android.content.res.Resources; -import android.os.Bundle; -import android.view.ViewGroup.LayoutParams; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.google.inject.Inject; - -public class InvitationCodeActivity extends RoboActivity -implements CodeEntryListener { - - @Inject private InvitationManager manager; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); - layout.setOrientation(VERTICAL); - layout.setGravity(CENTER_HORIZONTAL); - - TextView yourCode = new TextView(this); - yourCode.setGravity(CENTER_HORIZONTAL); - yourCode.setText(R.string.your_invitation_code); - layout.addView(yourCode); - - TextView code = new TextView(this); - code.setGravity(CENTER_HORIZONTAL); - code.setTextSize(50); - code.setText(manager.getLocalInvitationCode()); - layout.addView(code); - - CodeEntryWidget codeEntry = new CodeEntryWidget(this); - Resources res = getResources(); - codeEntry.init(this, res.getString(R.string.enter_invitation_code)); - layout.addView(codeEntry); - - setContentView(layout); - } - - public void codeEntered(String code) { - manager.setRemoteInvitationCode(code); - Intent intent = new Intent(this, ConnectionActivity.class); - intent.putExtras(getIntent().getExtras()); - startActivity(intent); - finish(); - } -} diff --git a/src/net/sf/briar/android/invitation/InvitationCodeView.java b/src/net/sf/briar/android/invitation/InvitationCodeView.java new file mode 100644 index 0000000000..fae6cca528 --- /dev/null +++ b/src/net/sf/briar/android/invitation/InvitationCodeView.java @@ -0,0 +1,46 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER_HORIZONTAL; +import net.sf.briar.R; +import android.content.Context; +import android.content.res.Resources; +import android.widget.TextView; + +public class InvitationCodeView extends AddContactView +implements CodeEntryListener { + + private int localCode = -1; + + InvitationCodeView(Context ctx) { + super(ctx); + } + + void init(AddContactActivity container) { + localCode = container.generateLocalInvitationCode(); + super.init(container); + } + + void populate() { + removeAllViews(); + Context ctx = getContext(); + TextView yourCode = new TextView(ctx); + yourCode.setGravity(CENTER_HORIZONTAL); + yourCode.setText(R.string.your_invitation_code); + addView(yourCode); + + TextView code = new TextView(ctx); + code.setGravity(CENTER_HORIZONTAL); + code.setTextSize(50); + code.setText(String.format("%06d", localCode)); + addView(code); + + CodeEntryWidget codeEntry = new CodeEntryWidget(ctx); + Resources res = getResources(); + codeEntry.init(this, res.getString(R.string.enter_invitation_code)); + addView(codeEntry); + } + + public void codeEntered(int remoteCode) { + container.remoteInvitationCodeEntered(remoteCode); + } +} diff --git a/src/net/sf/briar/android/invitation/InvitationManager.java b/src/net/sf/briar/android/invitation/InvitationManager.java deleted file mode 100644 index f77baa4c33..0000000000 --- a/src/net/sf/briar/android/invitation/InvitationManager.java +++ /dev/null @@ -1,26 +0,0 @@ -package net.sf.briar.android.invitation; - -import android.content.Context; - -interface InvitationManager { - - int TIMEOUT = 20 * 1000; - - void tryToConnect(ConnectionListener listener); - - String getLocalInvitationCode(); - - String getRemoteInvitationCode(); - - void setRemoteInvitationCode(String code); - - void startWifiConnectionWorker(Context ctx); - - void startBluetoothConnectionWorker(Context ctx); - - String getLocalConfirmationCode(); - - String getRemoteConfirmationCode(); - - void startConfirmationWorker(ConfirmationListener listener); -} diff --git a/src/net/sf/briar/android/invitation/InvitationManagerImpl.java b/src/net/sf/briar/android/invitation/InvitationManagerImpl.java deleted file mode 100644 index c5afcacec1..0000000000 --- a/src/net/sf/briar/android/invitation/InvitationManagerImpl.java +++ /dev/null @@ -1,67 +0,0 @@ -package net.sf.briar.android.invitation; - -import android.content.Context; -import android.util.Log; - -class InvitationManagerImpl implements InvitationManager { - - public void tryToConnect(final ConnectionListener listener) { - new Thread() { - @Override - public void run() { - try { - // FIXME - Thread.sleep((long) (Math.random() * TIMEOUT)); - if(Math.random() < 0.5) listener.connectionEstablished(); - else listener.connectionNotEstablished(); - } catch(InterruptedException e) { - Log.w(getClass().getName(), e.toString()); - listener.connectionNotEstablished(); - } - } - }.start(); - } - - public String getLocalInvitationCode() { - // FIXME - return "123456"; - } - - public String getRemoteInvitationCode() { - // FIXME - return "123456"; - } - - public void setRemoteInvitationCode(String code) { - // FIXME - } - - public void startWifiConnectionWorker(Context ctx) { - // FIXME - } - - public void startBluetoothConnectionWorker(Context ctx) { - // FIXME - } - - public String getLocalConfirmationCode() { - // FIXME - return "123456"; - } - - public String getRemoteConfirmationCode() { - // FIXME - return "123456"; - } - - public void startConfirmationWorker(ConfirmationListener listener) { - // FIXME - try { - Thread.sleep(1000 + (int) (Math.random() * 4 * 1000)); - } catch(InterruptedException e) { - Log.w(getClass().getName(), e.toString()); - Thread.currentThread().interrupt(); - } - listener.confirmationReceived(); - } -} diff --git a/src/net/sf/briar/android/invitation/NetworkSetupActivity.java b/src/net/sf/briar/android/invitation/NetworkSetupActivity.java deleted file mode 100644 index abe9065dbb..0000000000 --- a/src/net/sf/briar/android/invitation/NetworkSetupActivity.java +++ /dev/null @@ -1,99 +0,0 @@ -package net.sf.briar.android.invitation; - -import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; -import static android.widget.LinearLayout.VERTICAL; -import net.sf.briar.R; -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup.LayoutParams; -import android.widget.Button; -import android.widget.LinearLayout; -import android.widget.TextView; - -public class NetworkSetupActivity extends Activity -implements WifiStateListener, BluetoothStateListener, OnClickListener { - - private WifiWidget wifi = null; - private BluetoothWidget bluetooth = null; - private Button continueButton = null; - private String networkName = null; - private boolean useBluetooth = false; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); - layout.setOrientation(VERTICAL); - layout.setGravity(CENTER_HORIZONTAL); - - TextView sameNetwork = new TextView(this); - sameNetwork.setGravity(CENTER_HORIZONTAL); - sameNetwork.setText(R.string.same_network); - layout.addView(sameNetwork); - - wifi = new WifiWidget(this); - wifi.init(this); - layout.addView(wifi); - - bluetooth = new BluetoothWidget(this); - bluetooth.init(this); - layout.addView(bluetooth); - - continueButton = new Button(this); - LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT); - continueButton.setLayoutParams(lp); - continueButton.setText(R.string.continue_button); - continueButton.setOnClickListener(this); - enableOrDisableContinueButton(); - layout.addView(continueButton); - - setContentView(layout); - } - - @Override - public void onResume() { - super.onResume(); - wifi.populate(); - bluetooth.populate(); - } - - public void wifiStateChanged(final String name) { - runOnUiThread(new Runnable() { - public void run() { - networkName = name; - enableOrDisableContinueButton(); - } - }); - } - - public void bluetoothStateChanged(final boolean enabled) { - runOnUiThread(new Runnable() { - public void run() { - useBluetooth = enabled; - enableOrDisableContinueButton(); - } - }); - } - - private void enableOrDisableContinueButton() { - if(continueButton == null) return; // Activity not created yet - if(useBluetooth || networkName != null) continueButton.setEnabled(true); - else continueButton.setEnabled(false); - } - - public void onClick(View view) { - Intent intent = new Intent(this, InvitationCodeActivity.class); - intent.putExtra("net.sf.briar.android.invitation.NETWORK_NAME", - networkName); - intent.putExtra("net.sf.briar.android.invitation.USE_BLUETOOTH", - useBluetooth); - startActivity(intent); - finish(); - } -} diff --git a/src/net/sf/briar/android/invitation/NetworkSetupView.java b/src/net/sf/briar/android/invitation/NetworkSetupView.java new file mode 100644 index 0000000000..da4d7671ea --- /dev/null +++ b/src/net/sf/briar/android/invitation/NetworkSetupView.java @@ -0,0 +1,76 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER_HORIZONTAL; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import net.sf.briar.R; +import android.content.Context; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.TextView; + +public class NetworkSetupView extends AddContactView +implements WifiStateListener, BluetoothStateListener, OnClickListener { + + private Button continueButton = null; + + NetworkSetupView(Context ctx) { + super(ctx); + } + + void populate() { + removeAllViews(); + Context ctx = getContext(); + TextView sameNetwork = new TextView(ctx); + sameNetwork.setGravity(CENTER_HORIZONTAL); + sameNetwork.setText(R.string.same_network); + addView(sameNetwork); + + WifiWidget wifi = new WifiWidget(ctx); + wifi.init(this); + addView(wifi); + + BluetoothWidget bluetooth = new BluetoothWidget(ctx); + bluetooth.init(this); + addView(bluetooth); + + continueButton = new Button(ctx); + LayoutParams lp = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT); + continueButton.setLayoutParams(lp); + continueButton.setText(R.string.continue_button); + continueButton.setOnClickListener(this); + enableOrDisableContinueButton(); + addView(continueButton); + } + + public void wifiStateChanged(final String networkName) { + container.runOnUiThread(new Runnable() { + public void run() { + container.setNetworkName(networkName); + enableOrDisableContinueButton(); + } + }); + } + + public void bluetoothStateChanged(final boolean enabled) { + container.runOnUiThread(new Runnable() { + public void run() { + container.setUseBluetooth(enabled); + enableOrDisableContinueButton(); + } + }); + } + + private void enableOrDisableContinueButton() { + if(continueButton == null) return; // Activity not created yet + boolean useBluetooth = container.getUseBluetooth(); + String networkName = container.getNetworkName(); + if(useBluetooth || networkName != null) continueButton.setEnabled(true); + else continueButton.setEnabled(false); + } + + public void onClick(View view) { + // Continue + container.setView(new InvitationCodeView(container)); + } +} diff --git a/src/net/sf/briar/android/invitation/WaitForContactActivity.java b/src/net/sf/briar/android/invitation/WaitForContactActivity.java deleted file mode 100644 index 7d93aea62d..0000000000 --- a/src/net/sf/briar/android/invitation/WaitForContactActivity.java +++ /dev/null @@ -1,89 +0,0 @@ -package net.sf.briar.android.invitation; - -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.widget.LinearLayout.HORIZONTAL; -import static android.widget.LinearLayout.VERTICAL; -import net.sf.briar.R; -import roboguice.activity.RoboActivity; -import android.content.Intent; -import android.os.Bundle; -import android.view.ViewGroup.LayoutParams; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.TextView; - -import com.google.inject.Inject; - -public class WaitForContactActivity extends RoboActivity -implements ConfirmationListener { - - @Inject private InvitationManager manager; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); - layout.setOrientation(VERTICAL); - layout.setGravity(CENTER_HORIZONTAL); - - LinearLayout innerLayout = new LinearLayout(this); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ImageView icon = new ImageView(this); - icon.setPadding(10, 10, 10, 10); - icon.setImageResource(R.drawable.navigation_accept); - innerLayout.addView(icon); - - TextView failed = new TextView(this); - failed.setTextSize(20); - failed.setText(R.string.connected_to_contact); - innerLayout.addView(failed); - layout.addView(innerLayout); - - TextView yourCode = new TextView(this); - yourCode.setGravity(CENTER_HORIZONTAL); - yourCode.setText(R.string.your_confirmation_code); - layout.addView(yourCode); - - TextView code = new TextView(this); - code.setGravity(CENTER_HORIZONTAL); - code.setTextSize(50); - code.setText(manager.getLocalConfirmationCode()); - layout.addView(code); - - innerLayout = new LinearLayout(this); - innerLayout.setOrientation(HORIZONTAL); - innerLayout.setGravity(CENTER); - - ProgressBar progress = new ProgressBar(this); - progress.setIndeterminate(true); - progress.setPadding(0, 10, 10, 0); - innerLayout.addView(progress); - - TextView connecting = new TextView(this); - connecting.setText(R.string.waiting_for_contact); - innerLayout.addView(connecting); - layout.addView(innerLayout); - - setContentView(layout); - - manager.startConfirmationWorker(this); - } - - public void confirmationReceived() { - startActivity(new Intent(this, ContactAddedActivity.class)); - finish(); - } - - public void confirmationNotReceived() { - Intent intent = new Intent(this, CodesDoNotMatchActivity.class); - intent.putExtras(getIntent().getExtras()); - startActivity(intent); - finish(); - } -} diff --git a/src/net/sf/briar/android/invitation/WaitForContactView.java b/src/net/sf/briar/android/invitation/WaitForContactView.java new file mode 100644 index 0000000000..d7c5824cb6 --- /dev/null +++ b/src/net/sf/briar/android/invitation/WaitForContactView.java @@ -0,0 +1,62 @@ +package net.sf.briar.android.invitation; + +import static android.view.Gravity.CENTER; +import static android.view.Gravity.CENTER_HORIZONTAL; +import net.sf.briar.R; +import android.content.Context; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +public class WaitForContactView extends AddContactView { + + WaitForContactView(Context ctx) { + super(ctx); + } + + void populate() { + removeAllViews(); + Context ctx = getContext(); + LinearLayout innerLayout = new LinearLayout(ctx); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + + ImageView icon = new ImageView(ctx); + icon.setPadding(10, 10, 10, 10); + icon.setImageResource(R.drawable.navigation_accept); + innerLayout.addView(icon); + + TextView failed = new TextView(ctx); + failed.setTextSize(20); + failed.setText(R.string.connected_to_contact); + innerLayout.addView(failed); + addView(innerLayout); + + TextView yourCode = new TextView(ctx); + yourCode.setGravity(CENTER_HORIZONTAL); + yourCode.setText(R.string.your_confirmation_code); + addView(yourCode); + + TextView code = new TextView(ctx); + code.setGravity(CENTER_HORIZONTAL); + code.setTextSize(50); + int localCode = container.getLocalConfirmationCode(); + code.setText(String.format("%06d", localCode)); + addView(code); + + innerLayout = new LinearLayout(ctx); + innerLayout.setOrientation(HORIZONTAL); + innerLayout.setGravity(CENTER); + + ProgressBar progress = new ProgressBar(ctx); + progress.setIndeterminate(true); + progress.setPadding(0, 10, 10, 0); + innerLayout.addView(progress); + + TextView connecting = new TextView(ctx); + connecting.setText(R.string.waiting_for_contact); + innerLayout.addView(connecting); + addView(innerLayout); + } +} diff --git a/src/net/sf/briar/api/crypto/CryptoComponent.java b/src/net/sf/briar/api/crypto/CryptoComponent.java index c6e4b34fd9..ae63dfa3d2 100644 --- a/src/net/sf/briar/api/crypto/CryptoComponent.java +++ b/src/net/sf/briar/api/crypto/CryptoComponent.java @@ -11,7 +11,7 @@ public interface CryptoComponent { /** * Derives a tag key from the given temporary secret. - * @param alice Indicates whether the key is for connections initiated by + * @param alice indicates whether the key is for connections initiated by * Alice or Bob. */ ErasableKey deriveTagKey(byte[] secret, boolean alice); @@ -19,9 +19,9 @@ public interface CryptoComponent { /** * Derives a frame key from the given temporary secret and connection * number. - * @param alice Indicates whether the key is for a connection initiated by + * @param alice indicates whether the key is for a connection initiated by * Alice or Bob. - * @param initiator Indicates whether the key is for the initiator's or the + * @param initiator indicates whether the key is for the initiator's or the * responder's side of the connection. */ ErasableKey deriveFrameKey(byte[] secret, long connection, boolean alice, @@ -30,7 +30,7 @@ public interface CryptoComponent { /** * Derives an initial shared secret from two public keys and one of the * corresponding private keys. - * @param alice Indicates whether the private key belongs to Alice or Bob. + * @param alice indicates whether the private key belongs to Alice or Bob. */ byte[] deriveInitialSecret(byte[] ourPublicKey, byte[] theirPublicKey, PrivateKey ourPrivateKey, boolean alice); @@ -67,7 +67,7 @@ public interface CryptoComponent { MessageDigest getMessageDigest(); - PseudoRandom getPseudoRandom(int seed); + PseudoRandom getPseudoRandom(int seed1, int seed2); SecureRandom getSecureRandom(); diff --git a/src/net/sf/briar/api/db/DatabaseComponent.java b/src/net/sf/briar/api/db/DatabaseComponent.java index cc6ae698fa..b584830233 100644 --- a/src/net/sf/briar/api/db/DatabaseComponent.java +++ b/src/net/sf/briar/api/db/DatabaseComponent.java @@ -34,7 +34,7 @@ public interface DatabaseComponent { /** * Opens the database. - * @param resume True to reopen an existing database or false to create a + * @param resume true to reopen an existing database or false to create a * new one. */ void open(boolean resume) throws DbException, IOException; diff --git a/src/net/sf/briar/api/invitation/ConfirmationCallback.java b/src/net/sf/briar/api/invitation/ConfirmationCallback.java new file mode 100644 index 0000000000..652773f863 --- /dev/null +++ b/src/net/sf/briar/api/invitation/ConfirmationCallback.java @@ -0,0 +1,14 @@ +package net.sf.briar.api.invitation; + +/** An interface for informing a peer of whether confirmation codes match. */ +public interface ConfirmationCallback { + + /** Called to indicate that the confirmation codes match. */ + void codesMatch(); + + /** + * Called to indicate that either the confirmation codes do not match or + * the result of the comparison is unknown. + */ + void codesDoNotMatch(); +} diff --git a/src/net/sf/briar/api/invitation/ConnectionCallback.java b/src/net/sf/briar/api/invitation/ConnectionCallback.java new file mode 100644 index 0000000000..56ce5c73bf --- /dev/null +++ b/src/net/sf/briar/api/invitation/ConnectionCallback.java @@ -0,0 +1,18 @@ +package net.sf.briar.api.invitation; + +/** An interface for monitoring the status of an invitation connection. */ +public interface ConnectionCallback extends ConfirmationCallback { + + /** + * Called if the connection is successfully established. + * @param localCode the local confirmation code. + * @param remoteCode the remote confirmation code. + * @param c a callback to inform the remote peer of the result of the local + * peer's confirmation code comparison. + */ + void connectionEstablished(int localCode, int remoteCode, + ConfirmationCallback c); + + /** Called if the connection cannot be established. */ + void connectionNotEstablished(); +} diff --git a/src/net/sf/briar/api/invitation/InvitationManager.java b/src/net/sf/briar/api/invitation/InvitationManager.java new file mode 100644 index 0000000000..e0ae1774ce --- /dev/null +++ b/src/net/sf/briar/api/invitation/InvitationManager.java @@ -0,0 +1,17 @@ +package net.sf.briar.api.invitation; + +/** + * Allows invitation connections to be established and their status to be + * monitored. + */ +public interface InvitationManager { + + /** + * Tries to establish an invitation connection. + * @param localCode the local invitation code. + * @param remoteCode the remote invitation code. + * @param c1 a callback to be informed of the connection's status and the + * result of the remote peer's confirmation code comparison. + */ + void connect(int localCode, int remoteCode, ConnectionCallback c); +} diff --git a/src/net/sf/briar/api/plugins/InvitationConstants.java b/src/net/sf/briar/api/plugins/InvitationConstants.java index 6941ad0e0e..f27d35b825 100644 --- a/src/net/sf/briar/api/plugins/InvitationConstants.java +++ b/src/net/sf/briar/api/plugins/InvitationConstants.java @@ -6,9 +6,9 @@ public interface InvitationConstants { int CODE_BITS = 19; // Codes must fit into six decimal digits - int MAX_CODE = 1 << CODE_BITS - 1; + int MAX_CODE = (1 << CODE_BITS) - 1; - int HASH_LENGTH = 48; + int HASH_LENGTH = 48; // Bytes - int MAX_PUBLIC_KEY_LENGTH = 120; + int MAX_PUBLIC_KEY_LENGTH = 120; // Bytes } diff --git a/src/net/sf/briar/api/plugins/Plugin.java b/src/net/sf/briar/api/plugins/Plugin.java index 319f58148b..4debef1e29 100644 --- a/src/net/sf/briar/api/plugins/Plugin.java +++ b/src/net/sf/briar/api/plugins/Plugin.java @@ -21,14 +21,14 @@ public interface Plugin { void stop() throws IOException; /** - * Returns true if the plugin's poll() method should be called - * periodically to attempt to establish connections. + * Returns true if the plugin's {@link Plugin#poll(Collection)} method + * should be called periodically to attempt to establish connections. */ boolean shouldPoll(); /** * Returns the desired interval in milliseconds between calls to the - * plugin's poll() method. + * plugin's {@link Plugin#poll(Collection)} method. */ long getPollingInterval(); diff --git a/src/net/sf/briar/api/plugins/PluginCallback.java b/src/net/sf/briar/api/plugins/PluginCallback.java index 63435f9f50..895d4a8b25 100644 --- a/src/net/sf/briar/api/plugins/PluginCallback.java +++ b/src/net/sf/briar/api/plugins/PluginCallback.java @@ -33,7 +33,7 @@ public interface PluginCallback { * Presents the user with a choice among two or more named options and * returns the user's response. The message may consist of a translatable * format string and arguments. - * @return An index into the array of options indicating the user's choice, + * @return an index into the array of options indicating the user's choice, * or -1 if the user cancelled the choice. */ int showChoice(String[] options, String... message); diff --git a/src/net/sf/briar/api/plugins/PluginManager.java b/src/net/sf/briar/api/plugins/PluginManager.java index f3f49ab716..77bc1dc982 100644 --- a/src/net/sf/briar/api/plugins/PluginManager.java +++ b/src/net/sf/briar/api/plugins/PluginManager.java @@ -5,6 +5,10 @@ import java.util.Collection; import net.sf.briar.api.plugins.duplex.DuplexPlugin; import android.content.Context; +/** + * Responsible for starting transport plugins at startup, stopping them at + * shutdown, and providing access to plugins for exchanging invitations. + */ public interface PluginManager { /** diff --git a/src/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java b/src/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java index b7f0f35ed9..ffda7ef0d5 100644 --- a/src/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java +++ b/src/net/sf/briar/api/plugins/simplex/SimplexTransportReader.java @@ -9,8 +9,7 @@ import java.io.InputStream; */ public interface SimplexTransportReader { - /** Returns an input stream for reading from the transport. - * @throws IOException */ + /** Returns an input stream for reading from the transport. */ InputStream getInputStream() throws IOException; /** diff --git a/src/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java b/src/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java index c48b2795de..152b7fd673 100644 --- a/src/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java +++ b/src/net/sf/briar/api/plugins/simplex/SimplexTransportWriter.java @@ -12,8 +12,7 @@ public interface SimplexTransportWriter { /** Returns the capacity of the transport in bytes. */ long getCapacity(); - /** Returns an output stream for writing to the transport. - * @throws IOException */ + /** Returns an output stream for writing to the transport. */ OutputStream getOutputStream() throws IOException; /** diff --git a/src/net/sf/briar/api/ui/UiCallback.java b/src/net/sf/briar/api/ui/UiCallback.java index d241eadb37..4903ef89e5 100644 --- a/src/net/sf/briar/api/ui/UiCallback.java +++ b/src/net/sf/briar/api/ui/UiCallback.java @@ -6,7 +6,7 @@ public interface UiCallback { * Presents the user with a choice among two or more named options and * returns the user's response. The message may consist of a translatable * format string and arguments. - * @return An index into the array of options indicating the user's choice, + * @return an index into the array of options indicating the user's choice, * or -1 if the user cancelled the choice. */ int showChoice(String[] options, String... message); diff --git a/src/net/sf/briar/crypto/CryptoComponentImpl.java b/src/net/sf/briar/crypto/CryptoComponentImpl.java index bc1c07a53f..7ac9d230ec 100644 --- a/src/net/sf/briar/crypto/CryptoComponentImpl.java +++ b/src/net/sf/briar/crypto/CryptoComponentImpl.java @@ -274,8 +274,8 @@ class CryptoComponentImpl implements CryptoComponent { } } - public PseudoRandom getPseudoRandom(int seed) { - return new PseudoRandomImpl(getMessageDigest(), seed); + public PseudoRandom getPseudoRandom(int seed1, int seed2) { + return new PseudoRandomImpl(getMessageDigest(), seed1, seed2); } public SecureRandom getSecureRandom() { diff --git a/src/net/sf/briar/crypto/PseudoRandomImpl.java b/src/net/sf/briar/crypto/PseudoRandomImpl.java index 1f74586e4a..c2751cf25d 100644 --- a/src/net/sf/briar/crypto/PseudoRandomImpl.java +++ b/src/net/sf/briar/crypto/PseudoRandomImpl.java @@ -11,10 +11,11 @@ class PseudoRandomImpl implements PseudoRandom { private byte[] state; private int offset; - PseudoRandomImpl(MessageDigest messageDigest, int seed) { + PseudoRandomImpl(MessageDigest messageDigest, int seed1, int seed2) { this.messageDigest = messageDigest; - byte[] seedBytes = new byte[4]; - ByteUtils.writeUint32(seed, seedBytes, 0); + byte[] seedBytes = new byte[8]; + ByteUtils.writeUint32(seed1, seedBytes, 0); + ByteUtils.writeUint32(seed2, seedBytes, 4); messageDigest.update(seedBytes); state = messageDigest.digest(); offset = 0; diff --git a/src/net/sf/briar/db/Database.java b/src/net/sf/briar/db/Database.java index 5303fae3dc..3959e735d1 100644 --- a/src/net/sf/briar/db/Database.java +++ b/src/net/sf/briar/db/Database.java @@ -24,9 +24,9 @@ import net.sf.briar.api.transport.TemporarySecret; /** * A low-level interface to the database (DatabaseComponent provides a * high-level interface). Most operations take a transaction argument, which is - * obtained by calling startTransaction(). Every transaction must be - * terminated by calling either abortTransaction() or commitTransaction(), - * even if an exception is thrown. + * obtained by calling {@link #startTransaction()}. Every transaction must be + * terminated by calling either {@link #abortTransaction(T)} or + * {@link #commitTransaction(T)}, even if an exception is thrown. * <p> * Locking is provided by the DatabaseComponent implementation. To prevent * deadlock, locks must be acquired in the following order: @@ -45,7 +45,7 @@ interface Database<T> { /** * Opens the database. - * @param resume True to reopen an existing database, false to create a + * @param resume true to reopen an existing database, false to create a * new one. */ void open(boolean resume) throws DbException, IOException; diff --git a/src/net/sf/briar/db/DatabaseComponentImpl.java b/src/net/sf/briar/db/DatabaseComponentImpl.java index 147226633f..84d63e81fd 100644 --- a/src/net/sf/briar/db/DatabaseComponentImpl.java +++ b/src/net/sf/briar/db/DatabaseComponentImpl.java @@ -326,7 +326,7 @@ DatabaseCleaner.Callback { * that have changed from sendable to not sendable, or vice versa. * <p> * Locking: message write. - * @param increment True if the message's sendability has changed from 0 to + * @param increment true if the message's sendability has changed from 0 to * greater than 0, or false if it has changed from greater than 0 to 0. */ private int updateAncestorSendability(T txn, MessageId m, boolean increment) @@ -1396,7 +1396,7 @@ DatabaseCleaner.Callback { * the ancestors of those messages if necessary. * <p> * Locking: message write. - * @param increment True if the user's rating for the author has changed + * @param increment true if the user's rating for the author has changed * from not good to good, or false if it has changed from good to not good. */ private void updateAuthorSendability(T txn, AuthorId a, boolean increment) diff --git a/src/net/sf/briar/invitation/InvitationManagerImpl.java b/src/net/sf/briar/invitation/InvitationManagerImpl.java new file mode 100644 index 0000000000..4d4967a068 --- /dev/null +++ b/src/net/sf/briar/invitation/InvitationManagerImpl.java @@ -0,0 +1,81 @@ +package net.sf.briar.invitation; + +import java.util.Collection; + +import net.sf.briar.api.crypto.CryptoComponent; +import net.sf.briar.api.crypto.PseudoRandom; +import net.sf.briar.api.invitation.ConfirmationCallback; +import net.sf.briar.api.invitation.ConnectionCallback; +import net.sf.briar.api.invitation.InvitationManager; +import net.sf.briar.api.plugins.PluginManager; +import net.sf.briar.api.plugins.duplex.DuplexPlugin; + +import com.google.inject.Inject; + +class InvitationManagerImpl implements InvitationManager { + + private final CryptoComponent crypto; + private final PluginManager pluginManager; + + @Inject + InvitationManagerImpl(CryptoComponent crypto, PluginManager pluginManager) { + this.crypto = crypto; + this.pluginManager = pluginManager; + } + + public void connect(int localCode, int remoteCode, ConnectionCallback c) { + Collection<DuplexPlugin> plugins = pluginManager.getInvitationPlugins(); + // Alice is the party with the smaller invitation code + if(localCode < remoteCode) { + PseudoRandom r = crypto.getPseudoRandom(localCode, remoteCode); + startAliceInvitationWorker(plugins, r, c); + } else { + PseudoRandom r = crypto.getPseudoRandom(remoteCode, localCode); + startBobInvitationWorker(plugins, r, c); + } + } + + private void startAliceInvitationWorker(Collection<DuplexPlugin> plugins, + PseudoRandom r, ConnectionCallback c) { + // FIXME + new FakeWorkerThread(c).start(); + } + + private void startBobInvitationWorker(Collection<DuplexPlugin> plugins, + PseudoRandom r, ConnectionCallback c) { + // FIXME + new FakeWorkerThread(c).start(); + } + + private static class FakeWorkerThread extends Thread { + + private final ConnectionCallback callback; + + private FakeWorkerThread(ConnectionCallback callback) { + this.callback = callback; + } + + @Override + public void run() { + try { + Thread.sleep((long) (Math.random() * 30 * 1000)); + } catch(InterruptedException ignored) {} + if(Math.random() < 0.8) { + callback.connectionNotEstablished(); + } else { + callback.connectionEstablished(123456, 123456, + new ConfirmationCallback() { + + public void codesMatch() {} + + public void codesDoNotMatch() {} + }); + try { + Thread.sleep((long) (Math.random() * 10 * 1000)); + } catch(InterruptedException ignored) {} + if(Math.random() < 0.5) callback.codesMatch(); + else callback.codesDoNotMatch(); + } + } + } +} diff --git a/src/net/sf/briar/invitation/InvitationModule.java b/src/net/sf/briar/invitation/InvitationModule.java new file mode 100644 index 0000000000..41197dc7fc --- /dev/null +++ b/src/net/sf/briar/invitation/InvitationModule.java @@ -0,0 +1,13 @@ +package net.sf.briar.invitation; + +import net.sf.briar.api.invitation.InvitationManager; + +import com.google.inject.AbstractModule; + +public class InvitationModule extends AbstractModule { + + @Override + protected void configure() { + bind(InvitationManager.class).to(InvitationManagerImpl.class); + } +} diff --git a/src/net/sf/briar/plugins/PluginManagerImpl.java b/src/net/sf/briar/plugins/PluginManagerImpl.java index 4fb2748895..110e201c02 100644 --- a/src/net/sf/briar/plugins/PluginManagerImpl.java +++ b/src/net/sf/briar/plugins/PluginManagerImpl.java @@ -95,6 +95,7 @@ class PluginManagerImpl implements PluginManager { public synchronized int start(Context appContext) { Set<TransportId> ids = new HashSet<TransportId>(); // Instantiate and start the simplex plugins + if(LOG.isLoggable(INFO)) LOG.info("Starting simplex plugins"); for(String s : getSimplexPluginFactoryNames()) { try { Class<?> c = Class.forName(s); @@ -128,6 +129,7 @@ class PluginManagerImpl implements PluginManager { } } // Instantiate and start the duplex plugins + if(LOG.isLoggable(INFO)) LOG.info("Starting duplex plugins"); for(String s : getDuplexPluginFactoryNames()) { try { Class<?> c = Class.forName(s); @@ -161,6 +163,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); @@ -182,8 +185,10 @@ class PluginManagerImpl implements PluginManager { public synchronized int stop() { int stopped = 0; // Stop the poller + if(LOG.isLoggable(INFO)) LOG.info("Stopping poller"); poller.stop(); // Stop the simplex plugins + if(LOG.isLoggable(INFO)) LOG.info("Stopping simplex plugins"); for(SimplexPlugin plugin : simplexPlugins) { try { plugin.stop(); @@ -192,7 +197,9 @@ class PluginManagerImpl implements PluginManager { if(LOG.isLoggable(WARNING)) LOG.warning(e.toString()); } } + simplexPlugins.clear(); // Stop the duplex plugins + if(LOG.isLoggable(INFO)) LOG.info("Stopping duplex plugins"); for(DuplexPlugin plugin : duplexPlugins) { try { plugin.stop(); @@ -201,7 +208,9 @@ class PluginManagerImpl implements PluginManager { if(LOG.isLoggable(WARNING)) LOG.warning(e.toString()); } } + duplexPlugins.clear(); // Shut down the executors + if(LOG.isLoggable(INFO)) LOG.info("Stopping executors"); pluginExecutor.shutdown(); androidExecutor.shutdown(); // Return the number of plugins successfully stopped diff --git a/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java b/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java index 1c8b196c88..bfd543d06f 100644 --- a/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java +++ b/src/net/sf/briar/plugins/droidtooth/DroidtoothPlugin.java @@ -349,10 +349,10 @@ class DroidtoothPlugin implements DuplexPlugin { if(!running) return; } if(adapter.getScanMode() == SCAN_MODE_CONNECTABLE_DISCOVERABLE) return; - Intent intent = new Intent(ACTION_REQUEST_DISCOVERABLE); - intent.putExtra(EXTRA_DISCOVERABLE_DURATION, 60); - intent.addFlags(FLAG_ACTIVITY_NEW_TASK); - appContext.startActivity(intent); + Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE); + i.putExtra(EXTRA_DISCOVERABLE_DURATION, 120); + i.addFlags(FLAG_ACTIVITY_NEW_TASK); + appContext.startActivity(i); } private static class BluetoothStateReceiver extends BroadcastReceiver { diff --git a/src/net/sf/briar/transport/ConnectionWriterImpl.java b/src/net/sf/briar/transport/ConnectionWriterImpl.java index d27905938c..4d1b2c571a 100644 --- a/src/net/sf/briar/transport/ConnectionWriterImpl.java +++ b/src/net/sf/briar/transport/ConnectionWriterImpl.java @@ -11,7 +11,7 @@ import net.sf.briar.api.transport.ConnectionWriter; /** * A ConnectionWriter that buffers its input and writes a frame whenever there - * is a full frame to write or the flush() method is called. + * is a full frame to write or the {@link #flush()} method is called. * <p> * This class is not thread-safe. */ -- GitLab