diff --git a/MasterPassword/Java/masterpassword-algorithm/src/main/java/com/lyndir/masterpassword/MasterKey.java b/MasterPassword/Java/masterpassword-algorithm/src/main/java/com/lyndir/masterpassword/MasterKey.java
index f4faaf43..3d086aec 100644
--- a/MasterPassword/Java/masterpassword-algorithm/src/main/java/com/lyndir/masterpassword/MasterKey.java
+++ b/MasterPassword/Java/masterpassword-algorithm/src/main/java/com/lyndir/masterpassword/MasterKey.java
@@ -16,10 +16,12 @@ import org.jetbrains.annotations.NotNull;
public abstract class MasterKey {
@SuppressWarnings("UnusedDeclaration")
- private static final Logger logger = Logger.get( MasterKey.class );
+ private static final Logger logger = Logger.get( MasterKey.class );
+ private static boolean allowNativeByDefault = true;
@Nonnull
private final String fullName;
+ private boolean allowNative = allowNativeByDefault;
@Nullable
private byte[] masterKey;
@@ -46,6 +48,23 @@ public abstract class MasterKey {
throw new UnsupportedOperationException( "Unsupported version: " + version );
}
+ public static boolean isAllowNativeByDefault() {
+ return allowNativeByDefault;
+ }
+
+ /**
+ * Native libraries are useful for speeding up the performance of cryptographical functions.
+ * Sometimes, however, we may prefer to use Java-only code.
+ * For instance, for auditability / trust or because the native code doesn't work on our CPU/platform.
+ *
+ * This setter affects the default setting for any newly created {@link MasterKey}s.
+ *
+ * @param allowNative false to disallow the use of native libraries.
+ */
+ public static void setAllowNativeByDefault(final boolean allowNative) {
+ allowNativeByDefault = allowNative;
+ }
+
protected MasterKey(@NotNull final String fullName) {
this.fullName = fullName;
@@ -63,6 +82,15 @@ public abstract class MasterKey {
return fullName;
}
+ public boolean isAllowNative() {
+ return allowNative;
+ }
+
+ public MasterKey setAllowNative(final boolean allowNative) {
+ this.allowNative = allowNative;
+ return this;
+ }
+
@Nonnull
protected byte[] getKey() {
diff --git a/MasterPassword/Java/masterpassword-algorithm/src/main/java/com/lyndir/masterpassword/MasterKeyV0.java b/MasterPassword/Java/masterpassword-algorithm/src/main/java/com/lyndir/masterpassword/MasterKeyV0.java
index 4ece61c3..b84872ab 100644
--- a/MasterPassword/Java/masterpassword-algorithm/src/main/java/com/lyndir/masterpassword/MasterKeyV0.java
+++ b/MasterPassword/Java/masterpassword-algorithm/src/main/java/com/lyndir/masterpassword/MasterKeyV0.java
@@ -65,8 +65,15 @@ public class MasterKeyV0 extends MasterKey {
mpBytesBuf.get( mpBytes, 0, mpBytes.length );
Arrays.fill( mpBytesBuf.array(), (byte) 0 );
+ return scrypt( masterKeySalt, mpBytes );
+ }
+
+ protected byte[] scrypt(final byte[] masterKeySalt, final byte[] mpBytes) {
try {
- return SCrypt.scrypt( mpBytes, masterKeySalt, MP_N, MP_r, MP_p, MP_dkLen );
+ if (isAllowNative())
+ return SCrypt.scrypt( mpBytes, masterKeySalt, MP_N, MP_r, MP_p, MP_dkLen );
+ else
+ return SCrypt.scryptJ( mpBytes, masterKeySalt, MP_N, MP_r, MP_p, MP_dkLen );
}
catch (GeneralSecurityException e) {
logger.bug( e );
diff --git a/MasterPassword/Java/masterpassword-algorithm/src/main/java/com/lyndir/masterpassword/MasterKeyV3.java b/MasterPassword/Java/masterpassword-algorithm/src/main/java/com/lyndir/masterpassword/MasterKeyV3.java
index db8d87d5..bc620a5d 100644
--- a/MasterPassword/Java/masterpassword-algorithm/src/main/java/com/lyndir/masterpassword/MasterKeyV3.java
+++ b/MasterPassword/Java/masterpassword-algorithm/src/main/java/com/lyndir/masterpassword/MasterKeyV3.java
@@ -14,7 +14,7 @@ import javax.annotation.Nullable;
/**
* bugs:
* - no known issues.
- *
+ *
* @author lhunath, 2014-08-30
*/
public class MasterKeyV3 extends MasterKeyV2 {
@@ -46,17 +46,8 @@ public class MasterKeyV3 extends MasterKeyV2 {
ByteBuffer mpBytesBuf = MP_charset.encode( CharBuffer.wrap( masterPassword ) );
byte[] mpBytes = new byte[mpBytesBuf.remaining()];
mpBytesBuf.get( mpBytes, 0, mpBytes.length );
- Arrays.fill( mpBytesBuf.array(), (byte)0 );
+ Arrays.fill( mpBytesBuf.array(), (byte) 0 );
- try {
- return SCrypt.scrypt( mpBytes, masterKeySalt, MP_N, MP_r, MP_p, MP_dkLen );
- }
- catch (GeneralSecurityException e) {
- logger.bug( e );
- return null;
- }
- finally {
- Arrays.fill( mpBytes, (byte) 0 );
- }
+ return scrypt( masterKeySalt, mpBytes );
}
}
diff --git a/MasterPassword/Java/masterpassword-android/AndroidManifest.xml b/MasterPassword/Java/masterpassword-android/AndroidManifest.xml
index 2f9c1f5f..a3947036 100644
--- a/MasterPassword/Java/masterpassword-android/AndroidManifest.xml
+++ b/MasterPassword/Java/masterpassword-android/AndroidManifest.xml
@@ -12,13 +12,13 @@
android:icon="@drawable/icon"
android:label="@string/app_name"
android:allowBackup="true">
-
+
-
+
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/icon_gears.png b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/icon_gears.png
new file mode 100644
index 00000000..c939369e
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/icon_gears.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/icon_key.png b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/icon_key.png
new file mode 100644
index 00000000..25ea04cf
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/icon_key.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/icon_plus.png b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/icon_plus.png
new file mode 100644
index 00000000..53fec014
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/icon_plus.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/identity.png b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/identity.png
new file mode 100644
index 00000000..b166f8f9
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/identity.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/img_identity.png b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/img_identity.png
new file mode 100644
index 00000000..74b24312
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/img_identity.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/img_key.png b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/img_key.png
new file mode 100644
index 00000000..3156342d
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/img_key.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/img_stats.png b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/img_stats.png
new file mode 100644
index 00000000..13be8b1d
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable-mdpi/img_stats.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/icon_gears.png b/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/icon_gears.png
new file mode 100644
index 00000000..e4cbaf04
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/icon_gears.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/icon_key.png b/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/icon_key.png
new file mode 100644
index 00000000..af6c44cd
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/icon_key.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/icon_plus.png b/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/icon_plus.png
new file mode 100644
index 00000000..cffdd7d9
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/icon_plus.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/img_identity.png b/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/img_identity.png
new file mode 100644
index 00000000..1455cdb9
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/img_identity.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/img_key.png b/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/img_key.png
new file mode 100644
index 00000000..336ddd36
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/img_key.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/img_stats.png b/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/img_stats.png
new file mode 100644
index 00000000..61bfa3f3
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable-xhdpi/img_stats.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/drawable/divider.png b/MasterPassword/Java/masterpassword-android/res/drawable/divider.png
new file mode 100644
index 00000000..35cf2a23
Binary files /dev/null and b/MasterPassword/Java/masterpassword-android/res/drawable/divider.png differ
diff --git a/MasterPassword/Java/masterpassword-android/res/layout/activity_emergency.xml b/MasterPassword/Java/masterpassword-android/res/layout/activity_emergency.xml
index 2d8c6d95..4d578ce4 100644
--- a/MasterPassword/Java/masterpassword-android/res/layout/activity_emergency.xml
+++ b/MasterPassword/Java/masterpassword-android/res/layout/activity_emergency.xml
@@ -1,5 +1,6 @@
+
+
+ android:textSize="16sp" />
@@ -46,16 +54,24 @@
android:hint="@string/masterPassword_hint"
android:gravity="center"
android:textColor="#FFFFFF"
- android:textSize="18sp" />
+ android:textSize="16sp" />
+
+
+ android:textSize="16sp" />
@@ -115,54 +130,136 @@
android:id="@+id/maskPasswordField"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:textSize="14sp"
+ android:textSize="12sp"
android:textColor="@android:color/tertiary_text_dark"
android:text="@string/maskPassword" />
-
+ android:layout_marginTop="20dp"
+ android:layout_marginBottom="8dp"
+ android:importantForAccessibility="no"
+ android:src="@drawable/divider" />
-
+ style="?android:buttonBarStyle"
+ android:orientation="horizontal"
+ android:gravity="center">
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:layout_marginTop="8dp"
+ android:textSize="16sp"
+ android:text="@string/btn_tests"
+ android:onClick="integrityTests"
+ android:background="@android:color/transparent" />
+
+
+ tools:max="100"
+ tools:progress="80"
+ style="?android:progressBarStyleHorizontal" />
+ android:onClick="onAction" />
+
diff --git a/MasterPassword/Java/masterpassword-android/res/values/strings.xml b/MasterPassword/Java/masterpassword-android/res/values/strings.xml
index e01c7f06..ffd4b787 100644
--- a/MasterPassword/Java/masterpassword-android/res/values/strings.xml
+++ b/MasterPassword/Java/masterpassword-android/res/values/strings.xml
@@ -8,15 +8,18 @@
Your master password
eg. google.com
Tap to copy
- Password #
+ Type
+ Counter
Algorithm
+ Integrity Tests
Test suite unavailable.
- Exit
+ Retest
Testing device\'s password generation integrity…
Please Stand By…
Incompatible device or OS.
- Exit
+ Retest
Integrity checks passed!
Continue
+ Use native key derivation
diff --git a/MasterPassword/Java/masterpassword-android/src/main/java/com/lyndir/masterpassword/EmergencyActivity.java b/MasterPassword/Java/masterpassword-android/src/main/java/com/lyndir/masterpassword/EmergencyActivity.java
index cd738aa2..fb25c644 100644
--- a/MasterPassword/Java/masterpassword-android/src/main/java/com/lyndir/masterpassword/EmergencyActivity.java
+++ b/MasterPassword/Java/masterpassword-android/src/main/java/com/lyndir/masterpassword/EmergencyActivity.java
@@ -61,13 +61,13 @@ public class EmergencyActivity extends Activity {
EditText siteNameField;
@InjectView(R.id.siteTypeField)
- Spinner siteTypeField;
+ Button siteTypeField;
@InjectView(R.id.counterField)
- EditText counterField;
+ Button counterField;
@InjectView(R.id.siteVersionField)
- Spinner siteVersionField;
+ Button siteVersionField;
@InjectView(R.id.sitePasswordField)
Button sitePasswordField;
@@ -104,9 +104,9 @@ public class EmergencyActivity extends Activity {
fullNameField.setOnFocusChangeListener( updateMasterKey );
masterPasswordField.setOnFocusChangeListener( updateMasterKey );
siteNameField.addTextChangedListener( updateSitePassword );
- siteTypeField.setOnItemSelectedListener( updateSitePassword );
+// siteTypeField.setOnItemSelectedListener( updateSitePassword );
counterField.addTextChangedListener( updateSitePassword );
- siteVersionField.setOnItemSelectedListener( updateMasterKey );
+// siteVersionField.setOnItemSelectedListener( updateMasterKey );
sitePasswordField.addTextChangedListener( new ValueChangedListener() {
@Override
void update() {
@@ -127,11 +127,11 @@ public class EmergencyActivity extends Activity {
sitePasswordField.setTypeface( Res.sourceCodePro_Black );
sitePasswordField.setPaintFlags( sitePasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
- siteTypeField.setAdapter( new ArrayAdapter<>( this, R.layout.spinner_item, MPSiteType.forClass( MPSiteTypeClass.Generated ) ) );
- siteTypeField.setSelection( MPSiteType.GeneratedLong.ordinal() );
+// siteTypeField.setAdapter( new ArrayAdapter<>( this, R.layout.spinner_item, MPSiteType.forClass( MPSiteTypeClass.Generated ) ) );
+// siteTypeField.setSelection( MPSiteType.GeneratedLong.ordinal() );
- siteVersionField.setAdapter( new ArrayAdapter<>( this, R.layout.spinner_item, MasterKey.Version.values() ) );
- siteVersionField.setSelection( MasterKey.Version.CURRENT.ordinal() );
+// siteVersionField.setAdapter( new ArrayAdapter<>( this, R.layout.spinner_item, MasterKey.Version.values() ) );
+// siteVersionField.setSelection( MasterKey.Version.CURRENT.ordinal() );
rememberFullNameField.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() {
@Override
@@ -162,6 +162,8 @@ public class EmergencyActivity extends Activity {
protected void onResume() {
super.onResume();
+ MasterKey.setAllowNativeByDefault( isNativeKDFEnabled() );
+
fullNameField.setText( getPreferences( MODE_PRIVATE ).getString( "fullName", "" ) );
rememberFullNameField.setChecked( isRememberFullNameEnabled() );
forgetPasswordField.setChecked( isForgetPasswordEnabled() );
@@ -195,6 +197,10 @@ public class EmergencyActivity extends Activity {
super.onPause();
}
+ private boolean isNativeKDFEnabled() {
+ return getPreferences( MODE_PRIVATE ).getBoolean( "nativeKDF", MasterKey.isAllowNativeByDefault() );
+ }
+
private boolean isRememberFullNameEnabled() {
return getPreferences( MODE_PRIVATE ).getBoolean( "rememberFullName", false );
}
@@ -210,7 +216,7 @@ public class EmergencyActivity extends Activity {
private synchronized void updateMasterKey() {
final String fullName = fullNameField.getText().toString();
final char[] masterPassword = masterPasswordField.getText().toString().toCharArray();
- final MasterKey.Version version = (MasterKey.Version) siteVersionField.getSelectedItem();
+ final MasterKey.Version version = MasterKey.Version.CURRENT;//( MasterKey.Version) siteVersionField.getSelectedItem();
try {
if (fullName.hashCode() == hc_userName && Arrays.hashCode( masterPassword ) == hc_masterPassword &&
masterKeyFuture != null && masterKeyFuture.get().getAlgorithmVersion() == version)
@@ -265,8 +271,10 @@ public class EmergencyActivity extends Activity {
private void updateSitePassword() {
final String siteName = siteNameField.getText().toString();
- final MPSiteType type = (MPSiteType) siteTypeField.getSelectedItem();
- final UnsignedInteger counter = UnsignedInteger.valueOf( ifNotNullElse( counterField.getText(), "1" ).toString() );
+ final MPSiteType type = MPSiteType.GeneratedLong;//(MPSiteType) siteTypeField.getSelectedItem();
+ CharSequence counterText = counterField.getText();
+ final UnsignedInteger counter =
+ TextUtils.isEmpty( counterText )? UnsignedInteger.valueOf( 1L ): UnsignedInteger.valueOf( counterText.toString() );
if (masterKeyFuture == null || siteName.isEmpty() || type == null) {
sitePasswordField.setText( "" );
@@ -313,6 +321,10 @@ public class EmergencyActivity extends Activity {
} );
}
+ public void integrityTests(View view) {
+ TestActivity.startNoSkip( this );
+ }
+
public void copySitePassword(View view) {
final String currentSitePassword = this.sitePassword;
if (TextUtils.isEmpty( currentSitePassword ))
diff --git a/MasterPassword/Java/masterpassword-android/src/main/java/com/lyndir/masterpassword/TestActivity.java b/MasterPassword/Java/masterpassword-android/src/main/java/com/lyndir/masterpassword/TestActivity.java
index 62625fac..52937610 100644
--- a/MasterPassword/Java/masterpassword-android/src/main/java/com/lyndir/masterpassword/TestActivity.java
+++ b/MasterPassword/Java/masterpassword-android/src/main/java/com/lyndir/masterpassword/TestActivity.java
@@ -3,9 +3,10 @@ package com.lyndir.masterpassword;
import static com.lyndir.lhunath.opal.system.util.StringUtils.strf;
import android.app.*;
+import android.content.Context;
+import android.content.Intent;
import android.os.*;
import android.view.View;
-import android.view.WindowManager;
import android.widget.*;
import butterknife.ButterKnife;
import butterknife.InjectView;
@@ -21,7 +22,8 @@ import javax.annotation.Nullable;
public class TestActivity extends Activity implements MPTestSuite.Listener {
@SuppressWarnings("UnusedDeclaration")
- private static final Logger logger = Logger.get( TestActivity.class );
+ private static final Logger logger = Logger.get( TestActivity.class );
+ private static final String PREF_TESTS_PASSED = "integrityTestsPassed";
private final ListeningExecutorService backgroundExecutor = MoreExecutors.listeningDecorator( Executors.newSingleThreadExecutor() );
private final ListeningExecutorService mainExecutor = MoreExecutors.listeningDecorator( new MainThreadExecutor() );
@@ -38,20 +40,34 @@ public class TestActivity extends Activity implements MPTestSuite.Listener {
@InjectView(R.id.actionButton)
Button actionButton;
+ @InjectView(R.id.nativeKDF)
+ CheckBox nativeKDF;
+
private MPTestSuite testSuite;
private ListenableFuture testFuture;
private Runnable action;
private ImmutableSet testNames;
+ public static void startNoSkip(Context context) {
+ context.startActivity( new Intent( context, TestActivity.class ) );
+ }
+
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
Res.init( getResources() );
- getWindow().setFlags( WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE );
setContentView( R.layout.activity_test );
ButterKnife.inject( this );
+ nativeKDF.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
+ getPreferences( MODE_PRIVATE ).edit().putBoolean( "nativeKDF", isChecked ).apply();
+ MasterKey.setAllowNativeByDefault( isNativeKDFEnabled() );
+ }
+ } );
+
try {
setStatus( 0, 0, null );
testSuite = new MPTestSuite();
@@ -76,63 +92,59 @@ public class TestActivity extends Activity implements MPTestSuite.Listener {
}
}
- @Override
- protected void onStart() {
- super.onStart();
-
- final Set integrityTestsPassed = getPreferences( MODE_PRIVATE ).getStringSet( "integrityTestsPassed",
- ImmutableSet.of() );
- if (!FluentIterable.from( testNames ).anyMatch( new Predicate() {
- @Override
- public boolean apply(@Nullable final String testName) {
- return !integrityTestsPassed.contains( testName );
- }
- } )) {
- // None of the tests we need to perform were missing from the tests that have already been passed on this device.
- finish();
- EmergencyActivity.start( TestActivity.this );
- }
- }
-
@Override
protected void onResume() {
super.onResume();
- if (testFuture == null) {
- setStatus( R.string.tests_testing, R.string.tests_btn_testing, null );
- Futures.addCallback( testFuture = backgroundExecutor.submit( testSuite ), new FutureCallback() {
- @Override
- public void onSuccess(@Nullable final Boolean result) {
- if (result != null && result)
- setStatus( R.string.tests_passed, R.string.tests_btn_passed, new Runnable() {
- @Override
- public void run() {
- getPreferences( MODE_PRIVATE ).edit().putStringSet( "integrityTestsPassed", testNames ).apply();
- finish();
- EmergencyActivity.start( TestActivity.this );
- }
- } );
- else
- setStatus( R.string.tests_failed, R.string.tests_btn_failed, new Runnable() {
- @Override
- public void run() {
- finish();
- }
- } );
- }
+ nativeKDF.setChecked( isNativeKDFEnabled() );
- @Override
- public void onFailure(final Throwable t) {
- logger.err( t, "While running test suite" );
+ if (testFuture == null)
+ startTestSuite();
+ }
+
+ private boolean isNativeKDFEnabled() {
+ return getPreferences( MODE_PRIVATE ).getBoolean( "nativeKDF", MasterKey.isAllowNativeByDefault() );
+ }
+
+ private void startTestSuite() {
+ if (testFuture != null)
+ testFuture.cancel( true );
+
+ MasterKey.setAllowNativeByDefault( isNativeKDFEnabled() );
+
+ setStatus( R.string.tests_testing, R.string.tests_btn_testing, null );
+ Futures.addCallback( testFuture = backgroundExecutor.submit( testSuite ), new FutureCallback() {
+ @Override
+ public void onSuccess(@Nullable final Boolean result) {
+ if (result != null && result)
+ setStatus( R.string.tests_passed, R.string.tests_btn_passed, new Runnable() {
+ @Override
+ public void run() {
+ getPreferences( MODE_PRIVATE ).edit().putStringSet( PREF_TESTS_PASSED, testNames ).apply();
+ finish();
+ EmergencyActivity.start( TestActivity.this );
+ }
+ } );
+ else
setStatus( R.string.tests_failed, R.string.tests_btn_failed, new Runnable() {
@Override
public void run() {
- finish();
+ startTestSuite();
}
} );
- }
- }, mainExecutor );
- }
+ }
+
+ @Override
+ public void onFailure(final Throwable t) {
+ logger.err( t, "While running test suite" );
+ setStatus( R.string.tests_failed, R.string.tests_btn_failed, new Runnable() {
+ @Override
+ public void run() {
+ finish();
+ }
+ } );
+ }
+ }, mainExecutor );
}
public void onAction(View v) {