diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java index a76138c1f98b83e0230ae782e2ab7f4a8012380f..123ce4396f9b0d1e08a7c888792e5bca4cd304f7 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java @@ -43,7 +43,7 @@ public interface DatabaseComponent { * @throws DataTooOldException if the data uses an older schema than the * current code and cannot be migrated */ - boolean open() throws DbException; + boolean open(@Nullable MigrationListener listener) throws DbException; /** * Waits for any open transactions to finish and closes the database. diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/MigrationListener.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/MigrationListener.java new file mode 100644 index 0000000000000000000000000000000000000000..79e292a75f3b9afd9cb40b1c95911afbaa4223dd --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/MigrationListener.java @@ -0,0 +1,11 @@ +package org.briarproject.bramble.api.db; + +public interface MigrationListener { + + /** + * This is called when a migration is started while opening the database. + * It will be called once for each migration being applied. + */ + void onMigrationRun(); + +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/LifecycleManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/LifecycleManager.java index b70c9dec9b2a624e88d8d5dd9c7519810f9b08fb..5a036a3b6cc2005a36c28bbaacb67638256941a1 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/LifecycleManager.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/LifecycleManager.java @@ -29,6 +29,19 @@ public interface LifecycleManager { SUCCESS } + /** + * The state the lifecycle can be in. + * Returned by {@link #getLifecycleState()} + */ + enum LifecycleState { + + STARTING, MIGRATING_DATABASE, STARTING_SERVICES, RUNNING, STOPPING; + + public boolean isAfter(LifecycleState state) { + return ordinal() > state.ordinal(); + } + } + /** * Registers a {@link Service} to be started and stopped. */ @@ -76,4 +89,10 @@ public interface LifecycleManager { * the {@link DatabaseComponent} to be closed before returning. */ void waitForShutdown() throws InterruptedException; + + /** + * Returns the current state of the lifecycle. + */ + LifecycleState getLifecycleState(); + } \ No newline at end of file diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/event/LifecycleEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/event/LifecycleEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..4e6370bcfb0064b42f6391f141b4fc8702778a0b --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/event/LifecycleEvent.java @@ -0,0 +1,20 @@ +package org.briarproject.bramble.api.lifecycle.event; + +import org.briarproject.bramble.api.event.Event; +import org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState; + +/** + * An event that is broadcast when the app enters a new lifecycle state. + */ +public class LifecycleEvent extends Event { + + private final LifecycleState state; + + public LifecycleEvent(LifecycleState state) { + this.state = state; + } + + public LifecycleState getLifecycleState() { + return state; + } +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/event/ShutdownEvent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/event/ShutdownEvent.java deleted file mode 100644 index ba0c4d37f03e963483432eb115070379d2abbcc5..0000000000000000000000000000000000000000 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/lifecycle/event/ShutdownEvent.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.briarproject.bramble.api.lifecycle.event; - -import org.briarproject.bramble.api.event.Event; - -/** - * An event that is broadcast when the app is shutting down. - */ -public class ShutdownEvent extends Event { -} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java index 9d1c7636498a869c856ad57a134514725fdd2dbc..0a6e54fbd85d47b5417444ab5b0c2b0513004289 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java @@ -6,6 +6,7 @@ import org.briarproject.bramble.api.db.DataTooNewException; import org.briarproject.bramble.api.db.DataTooOldException; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.Metadata; +import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.LocalAuthor; @@ -45,7 +46,7 @@ interface Database<T> { * @throws DataTooOldException if the data uses an older schema than the * current code and cannot be migrated */ - boolean open() throws DbException; + boolean open(@Nullable MigrationListener listener) throws DbException; /** * Prevents new transactions from starting, waits for all current diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java index af80da92b3c7f8d7499b1a0e126d0af9f75f42e0..5809c09eef279fb8b284c31bfb5b049027d28a57 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java @@ -10,6 +10,7 @@ import org.briarproject.bramble.api.db.ContactExistsException; import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.Metadata; +import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.db.NoSuchContactException; import org.briarproject.bramble.api.db.NoSuchGroupException; import org.briarproject.bramble.api.db.NoSuchLocalAuthorException; @@ -100,8 +101,9 @@ class DatabaseComponentImpl<T> implements DatabaseComponent { } @Override - public boolean open() throws DbException { - boolean reopened = db.open(); + public boolean open(@Nullable MigrationListener listener) + throws DbException { + boolean reopened = db.open(listener); shutdown.addShutdownHook(() -> { try { close(); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java index 6a81969260df8283a07c2ee9ab6a48efdd040778..1c1983e6771a2cc174ebcbf68ede5879aab7569f 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java @@ -3,6 +3,7 @@ package org.briarproject.bramble.db; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.util.StringUtils; @@ -13,6 +14,7 @@ import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; +import javax.annotation.Nullable; import javax.inject.Inject; /** @@ -42,10 +44,11 @@ class H2Database extends JdbcDatabase { } @Override - public boolean open() throws DbException { + public boolean open(@Nullable MigrationListener listener) + throws DbException { boolean reopen = config.databaseExists(); if (!reopen) config.getDatabaseDirectory().mkdirs(); - super.open("org.h2.Driver", reopen); + super.open("org.h2.Driver", reopen, listener); return reopen; } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/HyperSqlDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/HyperSqlDatabase.java index 1db9248cb28b6d67f7de3818b822480296dabf5e..6a87ededae7b862c992745f15ac5695f881a6cf0 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/HyperSqlDatabase.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/HyperSqlDatabase.java @@ -3,6 +3,7 @@ package org.briarproject.bramble.db; import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.util.StringUtils; @@ -13,6 +14,7 @@ import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; +import javax.annotation.Nullable; import javax.inject.Inject; /** @@ -44,10 +46,10 @@ class HyperSqlDatabase extends JdbcDatabase { } @Override - public boolean open() throws DbException { + public boolean open(@Nullable MigrationListener listener) throws DbException { boolean reopen = config.databaseExists(); if (!reopen) config.getDatabaseDirectory().mkdirs(); - super.open("org.hsqldb.jdbc.JDBCDriver", reopen); + super.open("org.hsqldb.jdbc.JDBCDriver", reopen, listener); return reopen; } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java index f1f795a8c1eb85cb33dd73c7894ad144a9649fde..e71f30c587215dda0cd8510981258e5fdc94c548 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java @@ -8,6 +8,7 @@ import org.briarproject.bramble.api.db.DataTooOldException; import org.briarproject.bramble.api.db.DbClosedException; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.Metadata; +import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.LocalAuthor; @@ -301,7 +302,8 @@ abstract class JdbcDatabase implements Database<Connection> { this.clock = clock; } - protected void open(String driverClass, boolean reopen) throws DbException { + protected void open(String driverClass, boolean reopen, + @Nullable MigrationListener listener) throws DbException { // Load the JDBC driver try { Class.forName(driverClass); @@ -312,7 +314,7 @@ abstract class JdbcDatabase implements Database<Connection> { Connection txn = startTransaction(); try { if (reopen) { - checkSchemaVersion(txn); + checkSchemaVersion(txn, listener); } else { createTables(txn); storeSchemaVersion(txn, CODE_SCHEMA_VERSION); @@ -335,7 +337,8 @@ abstract class JdbcDatabase implements Database<Connection> { * @throws DataTooOldException if the data uses an older schema than the * current code and cannot be migrated */ - private void checkSchemaVersion(Connection txn) throws DbException { + private void checkSchemaVersion(Connection txn, + @Nullable MigrationListener listener) throws DbException { Settings s = getSettings(txn, DB_SETTINGS_NAMESPACE); int dataSchemaVersion = s.getInt(SCHEMA_VERSION_KEY, -1); if (dataSchemaVersion == -1) throw new DbException(); @@ -348,6 +351,7 @@ abstract class JdbcDatabase implements Database<Connection> { if (start == dataSchemaVersion) { if (LOG.isLoggable(INFO)) LOG.info("Migrating from schema " + start + " to " + end); + if (listener != null) listener.onMigrationRun(); // Apply the migration m.migrate(txn); // Store the new schema version diff --git a/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java index 029170c911c4814c76b020115c6172a47ef12f79..0f41cbf211676f5427b56591a24e872c085ecef9 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java @@ -6,6 +6,7 @@ import org.briarproject.bramble.api.db.DataTooNewException; import org.briarproject.bramble.api.db.DataTooOldException; import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.MigrationListener; import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.identity.AuthorFactory; @@ -14,7 +15,7 @@ import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.Service; import org.briarproject.bramble.api.lifecycle.ServiceException; -import org.briarproject.bramble.api.lifecycle.event.ShutdownEvent; +import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.Client; @@ -31,6 +32,11 @@ import javax.inject.Inject; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE; +import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING; +import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING; +import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES; +import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.DATA_TOO_NEW_ERROR; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.DATA_TOO_OLD_ERROR; @@ -40,7 +46,7 @@ import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResul @ThreadSafe @NotNullByDefault -class LifecycleManagerImpl implements LifecycleManager { +class LifecycleManagerImpl implements LifecycleManager, MigrationListener { private static final Logger LOG = Logger.getLogger(LifecycleManagerImpl.class.getName()); @@ -58,6 +64,8 @@ class LifecycleManagerImpl implements LifecycleManager { private final CountDownLatch startupLatch = new CountDownLatch(1); private final CountDownLatch shutdownLatch = new CountDownLatch(1); + private volatile LifecycleState state = STARTING; + @Inject LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus, CryptoComponent crypto, AuthorFactory authorFactory, @@ -123,7 +131,7 @@ class LifecycleManagerImpl implements LifecycleManager { LOG.info("Starting services"); long start = System.currentTimeMillis(); - boolean reopened = db.open(); + boolean reopened = db.open(this); long duration = System.currentTimeMillis() - start; if (LOG.isLoggable(INFO)) { if (reopened) @@ -135,7 +143,10 @@ class LifecycleManagerImpl implements LifecycleManager { registerLocalAuthor(createLocalAuthor(nickname)); } + state = STARTING_SERVICES; dbLatch.countDown(); + eventBus.broadcast(new LifecycleEvent(STARTING_SERVICES)); + Transaction txn = db.startTransaction(false); try { for (Client c : clients) { @@ -161,7 +172,10 @@ class LifecycleManagerImpl implements LifecycleManager { + " took " + duration + " ms"); } } + + state = RUNNING; startupLatch.countDown(); + eventBus.broadcast(new LifecycleEvent(RUNNING)); return SUCCESS; } catch (DataTooOldException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); @@ -180,6 +194,12 @@ class LifecycleManagerImpl implements LifecycleManager { } } + @Override + public void onMigrationRun() { + state = MIGRATING_DATABASE; + eventBus.broadcast(new LifecycleEvent(MIGRATING_DATABASE)); + } + @Override public void stopServices() { try { @@ -190,7 +210,8 @@ class LifecycleManagerImpl implements LifecycleManager { } try { LOG.info("Stopping services"); - eventBus.broadcast(new ShutdownEvent()); + state = STOPPING; + eventBus.broadcast(new LifecycleEvent(STOPPING)); for (Service s : services) { long start = System.currentTimeMillis(); s.stopService(); @@ -235,4 +256,8 @@ class LifecycleManagerImpl implements LifecycleManager { shutdownLatch.await(); } + @Override + public LifecycleState getLifecycleState() { + return state; + } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/DuplexOutgoingSession.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/DuplexOutgoingSession.java index 3fdabc01dcc239959f3c54d339c050cc7e6d4536..80f699a1f9e6ebdb134ae0835541018992c6c406 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/DuplexOutgoingSession.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/DuplexOutgoingSession.java @@ -10,7 +10,7 @@ import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventListener; import org.briarproject.bramble.api.lifecycle.IoExecutor; -import org.briarproject.bramble.api.lifecycle.event.ShutdownEvent; +import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.Ack; import org.briarproject.bramble.api.sync.Offer; @@ -38,6 +38,7 @@ import javax.annotation.concurrent.ThreadSafe; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_RECORD_PAYLOAD_LENGTH; @@ -209,8 +210,9 @@ class DuplexOutgoingSession implements SyncSession, EventListener { } else if (e instanceof MessageToRequestEvent) { if (((MessageToRequestEvent) e).getContactId().equals(contactId)) generateRequest(); - } else if (e instanceof ShutdownEvent) { - interrupt(); + } else if (e instanceof LifecycleEvent) { + LifecycleEvent l = (LifecycleEvent) e; + if (l.getLifecycleState() == STOPPING) interrupt(); } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java index 249d1f2c6be2e227f557b84b36131f567f10fcdb..32eb58df4854d87c080671e913926e7dd3a2e925 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/IncomingSession.java @@ -11,7 +11,7 @@ import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventListener; import org.briarproject.bramble.api.lifecycle.IoExecutor; -import org.briarproject.bramble.api.lifecycle.event.ShutdownEvent; +import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.Ack; import org.briarproject.bramble.api.sync.Message; @@ -27,6 +27,7 @@ import java.util.logging.Logger; import javax.annotation.concurrent.ThreadSafe; import static java.util.logging.Level.WARNING; +import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING; /** * An incoming {@link SyncSession}. @@ -96,8 +97,9 @@ class IncomingSession implements SyncSession, EventListener { if (e instanceof ContactRemovedEvent) { ContactRemovedEvent c = (ContactRemovedEvent) e; if (c.getContactId().equals(contactId)) interrupt(); - } else if (e instanceof ShutdownEvent) { - interrupt(); + } else if (e instanceof LifecycleEvent) { + LifecycleEvent l = (LifecycleEvent) e; + if (l.getLifecycleState() == STOPPING) interrupt(); } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/sync/SimplexOutgoingSession.java b/bramble-core/src/main/java/org/briarproject/bramble/sync/SimplexOutgoingSession.java index 3d0ecae22b739912b498e380156a9970eedb2028..b1f8198f86dcb6b0d771527876de0ce9261ab057 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/sync/SimplexOutgoingSession.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/sync/SimplexOutgoingSession.java @@ -10,7 +10,7 @@ import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventListener; import org.briarproject.bramble.api.lifecycle.IoExecutor; -import org.briarproject.bramble.api.lifecycle.event.ShutdownEvent; +import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.sync.Ack; import org.briarproject.bramble.api.sync.RecordWriter; @@ -28,6 +28,7 @@ import javax.annotation.concurrent.ThreadSafe; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_RECORD_PAYLOAD_LENGTH; @@ -109,8 +110,9 @@ class SimplexOutgoingSession implements SyncSession, EventListener { if (e instanceof ContactRemovedEvent) { ContactRemovedEvent c = (ContactRemovedEvent) e; if (c.getContactId().equals(contactId)) interrupt(); - } else if (e instanceof ShutdownEvent) { - interrupt(); + } else if (e instanceof LifecycleEvent) { + LifecycleEvent l = (LifecycleEvent) e; + if (l.getLifecycleState() == STOPPING) interrupt(); } } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java index b2e4842db87c3f0a6633f1196756be456b7671b9..18de0d7e847f57156dd7ebbcab6474bd63e21404 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java @@ -134,7 +134,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { int shutdownHandle = 12345; context.checking(new Expectations() {{ // open() - oneOf(database).open(); + oneOf(database).open(null); will(returnValue(false)); oneOf(shutdown).addShutdownHook(with(any(Runnable.class))); will(returnValue(shutdownHandle)); @@ -201,7 +201,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { DatabaseComponent db = createDatabaseComponent(database, eventBus, shutdown); - assertFalse(db.open()); + assertFalse(db.open(null)); Transaction transaction = db.startTransaction(false); try { db.addLocalAuthor(transaction, localAuthor); @@ -1501,7 +1501,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { MessageId messageId2 = new MessageId(TestUtils.getRandomId()); context.checking(new Expectations() {{ // open() - oneOf(database).open(); + oneOf(database).open(null); will(returnValue(false)); oneOf(shutdown).addShutdownHook(with(any(Runnable.class))); will(returnValue(shutdownHandle)); @@ -1543,7 +1543,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { DatabaseComponent db = createDatabaseComponent(database, eventBus, shutdown); - assertFalse(db.open()); + assertFalse(db.open(null)); Transaction transaction = db.startTransaction(false); try { db.addLocalMessage(transaction, message, metadata, true); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseMigrationTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseMigrationTest.java index 203f4dfd21f6fd2b09ceed436f3a10dfca9696b7..89bdf8a4c1a8da94963bc41c7473be59b3f7c063 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseMigrationTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseMigrationTest.java @@ -62,7 +62,7 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { public void testDoesNotRunMigrationsWhenCreatingDatabase() throws Exception { Database<Connection> db = createDatabase(singletonList(migration)); - assertFalse(db.open()); + assertFalse(db.open(null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); db.close(); } @@ -72,14 +72,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { throws Exception { // Open the DB for the first time Database<Connection> db = createDatabase(asList(migration, migration1)); - assertFalse(db.open()); + assertFalse(db.open(null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); // Override the data schema version setDataSchemaVersion(db, -1); db.close(); // Reopen the DB - an exception should be thrown db = createDatabase(asList(migration, migration1)); - db.open(); + db.open(null); } @Test @@ -87,12 +87,12 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { throws Exception { // Open the DB for the first time Database<Connection> db = createDatabase(asList(migration, migration1)); - assertFalse(db.open()); + assertFalse(db.open(null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); db.close(); // Reopen the DB - migrations should not be run db = createDatabase(asList(migration, migration1)); - assertTrue(db.open()); + assertTrue(db.open(null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); db.close(); } @@ -101,14 +101,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { public void testThrowsExceptionIfDataIsNewerThanCode() throws Exception { // Open the DB for the first time Database<Connection> db = createDatabase(asList(migration, migration1)); - assertFalse(db.open()); + assertFalse(db.open(null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); // Override the data schema version setDataSchemaVersion(db, CODE_SCHEMA_VERSION + 1); db.close(); // Reopen the DB - an exception should be thrown db = createDatabase(asList(migration, migration1)); - db.open(); + db.open(null); } @Test(expected = DataTooOldException.class) @@ -116,13 +116,13 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { throws Exception { // Open the DB for the first time Database<Connection> db = createDatabase(emptyList()); - assertFalse(db.open()); + assertFalse(db.open(null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 1); db.close(); // Reopen the DB - an exception should be thrown db = createDatabase(emptyList()); - db.open(); + db.open(null); } @Test(expected = DataTooOldException.class) @@ -141,14 +141,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { // Open the DB for the first time Database<Connection> db = createDatabase(asList(migration, migration1)); - assertFalse(db.open()); + assertFalse(db.open(null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); // Override the data schema version setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 3); db.close(); // Reopen the DB - an exception should be thrown db = createDatabase(asList(migration, migration1)); - db.open(); + db.open(null); } @Test @@ -170,14 +170,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { // Open the DB for the first time Database<Connection> db = createDatabase(asList(migration, migration1)); - assertFalse(db.open()); + assertFalse(db.open(null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); // Override the data schema version setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 2); db.close(); // Reopen the DB - the first migration should be run db = createDatabase(asList(migration, migration1)); - assertTrue(db.open()); + assertTrue(db.open(null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); db.close(); } @@ -202,14 +202,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { // Open the DB for the first time Database<Connection> db = createDatabase(asList(migration, migration1)); - assertFalse(db.open()); + assertFalse(db.open(null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); // Override the data schema version setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 2); db.close(); // Reopen the DB - both migrations should be run db = createDatabase(asList(migration, migration1)); - assertTrue(db.open()); + assertTrue(db.open(null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); db.close(); } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabasePerformanceComparisonTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabasePerformanceComparisonTest.java index c2a124bb299c1729be0e9c83da3ad7555c65b82c..1807d30dc33374654a740b4acb58336bee1f5b52 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabasePerformanceComparisonTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabasePerformanceComparisonTest.java @@ -71,7 +71,7 @@ public abstract class DatabasePerformanceComparisonTest throws DbException { Database<Connection> db = createDatabase(conditionA, new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock()); - db.open(); + db.open(null); return db; } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseTraceTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseTraceTest.java index a78fb5f55a4aa93fd3929bd6e583c5e6a676cf6c..f4e0daa19dedf3d6e0187a4aa1b7e8d181136906 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseTraceTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseTraceTest.java @@ -43,7 +43,7 @@ public abstract class DatabaseTraceTest extends DatabasePerformanceTest { private Database<Connection> openDatabase() throws DbException { Database<Connection> db = createDatabase( new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock()); - db.open(); + db.open(null); return db; } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java index 32d4e5faa4b36b6330f0eeb1c2ab404dde264d7d..81d1c902578e1eaa6f7b6e3ba84fda69ad9a5b0a 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java @@ -1700,7 +1700,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { Database<Connection> db = createDatabase( new TestDatabaseConfig(testDir, MAX_SIZE), clock); if (!resume) TestUtils.deleteTestDirectory(testDir); - db.open(); + db.open(null); return db; } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/SingleDatabasePerformanceTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/SingleDatabasePerformanceTest.java index 5a836476782da918dc9047721839c60402f5a76b..670c7cddb79746be691317387a0c779d0c6b5213 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/SingleDatabasePerformanceTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/SingleDatabasePerformanceTest.java @@ -40,7 +40,7 @@ public abstract class SingleDatabasePerformanceTest private Database<Connection> openDatabase() throws DbException { Database<Connection> db = createDatabase( new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock()); - db.open(); + db.open(null); return db; } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/TestLifecycleModule.java b/bramble-core/src/test/java/org/briarproject/bramble/test/TestLifecycleModule.java index ee8d5115e07b3285bb0ac5be2251878102d84935..15943adc2b6dabfa86fc8ebb72d270ad396a00ed 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/test/TestLifecycleModule.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/test/TestLifecycleModule.java @@ -17,6 +17,8 @@ import javax.inject.Singleton; import dagger.Module; import dagger.Provides; +import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING; + @Module public class TestLifecycleModule { @@ -57,6 +59,11 @@ public class TestLifecycleModule { @Override public void waitForShutdown() throws InterruptedException { } + + @Override + public LifecycleState getLifecycleState() { + return RUNNING; + } }; return lifecycleManager; } diff --git a/briar-android/src/main/AndroidManifest.xml b/briar-android/src/main/AndroidManifest.xml index a2fed381f9a296c31c69b8e918ab4d7658b49c2e..102de1290c936f258fbc59e2c1714eda23fe5320 100644 --- a/briar-android/src/main/AndroidManifest.xml +++ b/briar-android/src/main/AndroidManifest.xml @@ -77,6 +77,11 @@ </intent-filter> </activity> + <activity + android:name=".android.login.OpenDatabaseActivity" + android:label="@string/app_name" + android:launchMode="singleTop"/> + <activity android:name="org.briarproject.briar.android.navdrawer.NavDrawerActivity" android:theme="@style/BriarTheme.NoActionBar" diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java index eba5d57eec64dfdc9645227d19e8809ecc793702..67af25ac69474c763f47a3ec09f3d483afec0feb 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java @@ -94,6 +94,7 @@ public class AppModule { @Override public boolean databaseExists() { + // FIXME should not run on UiThread #620 if (!dir.isDirectory()) return false; File[] files = dir.listFiles(); return files != null && files.length > 0; diff --git a/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java b/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java index abd9a20a7977c2ff452fbdcb4f1cb86bb5e9014b..8e1abd66a2ac03720c8190175a7c8308f71a7f3a 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/BriarService.java @@ -88,6 +88,7 @@ public class BriarService extends Service { stopSelf(); return; } + // Create notification channels if (SDK_INT >= 26) { NotificationManager nm = (NotificationManager) diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java index 7403d01e019fa91893cb2b59ea45faf243131f5c..2f8ca83faa6bd97999870c692cf6452479a23f70 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java @@ -32,6 +32,7 @@ import org.briarproject.briar.android.keyagreement.ShowQrCodeFragment; import org.briarproject.briar.android.login.AuthorNameFragment; import org.briarproject.briar.android.login.ChangePasswordActivity; import org.briarproject.briar.android.login.DozeFragment; +import org.briarproject.briar.android.login.OpenDatabaseActivity; import org.briarproject.briar.android.login.PasswordActivity; import org.briarproject.briar.android.login.PasswordFragment; import org.briarproject.briar.android.login.SetupActivity; @@ -88,6 +89,8 @@ public interface ActivityComponent { void inject(SetupActivity activity); + void inject(OpenDatabaseActivity activity); + void inject(NavDrawerActivity activity); void inject(PasswordActivity activity); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigController.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigController.java index d6bc554f6ee29d356e0e70d68f5a56f60b6a15d1..07b32b0e2f53bf2bd6f65b6aa165aff1c39c1411 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigController.java @@ -17,4 +17,7 @@ public interface ConfigController { void deleteAccount(Context ctx); boolean accountExists(); + + boolean accountSignedIn(); + } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java index 0af60bb981d993699630a665699b2dfbf769aef4..3c19794441e0d0b3e335b824de0530c13587e810 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java @@ -52,4 +52,10 @@ public class ConfigControllerImpl implements ConfigController { String hex = getEncryptedDatabaseKey(); return hex != null && databaseConfig.databaseExists(); } + + @Override + public boolean accountSignedIn() { + return databaseConfig.getEncryptionKey() != null; + } + } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/OpenDatabaseActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/login/OpenDatabaseActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..d24196d32b8a56d69dd2925fc8575a52d41b0a74 --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/OpenDatabaseActivity.java @@ -0,0 +1,93 @@ +package org.briarproject.briar.android.login; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.widget.ImageView; +import android.widget.TextView; + +import org.briarproject.bramble.api.event.Event; +import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.event.EventListener; +import org.briarproject.bramble.api.lifecycle.LifecycleManager; +import org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState; +import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent; +import org.briarproject.briar.R; +import org.briarproject.briar.android.activity.ActivityComponent; +import org.briarproject.briar.android.activity.BriarActivity; +import org.briarproject.briar.android.navdrawer.NavDrawerActivity; + +import javax.annotation.ParametersAreNonnullByDefault; +import javax.inject.Inject; + +import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE; +import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES; + +@ParametersAreNonnullByDefault +public class OpenDatabaseActivity extends BriarActivity + implements EventListener { + + @Inject + LifecycleManager lifecycleManager; + @Inject + EventBus eventBus; + + private TextView textView; + private ImageView imageView; + private boolean showingMigration = false; + + @Override + public void onCreate(@Nullable Bundle state) { + super.onCreate(state); + setContentView(R.layout.activity_open_database); + textView = findViewById(R.id.textView); + imageView = findViewById(R.id.imageView); + } + + @Override + public void injectActivity(ActivityComponent component) { + component.inject(this); + } + + @Override + public void onStart() { + super.onStart(); + LifecycleState state = lifecycleManager.getLifecycleState(); + if (state.isAfter(STARTING_SERVICES)) { + finishAndStartApp(); + } else { + if (state == MIGRATING_DATABASE) showMigration(); + eventBus.addListener(this); + } + } + + @Override + protected void onStop() { + super.onStop(); + eventBus.removeListener(this); + } + + @Override + public void eventOccurred(Event e) { + if (e instanceof LifecycleEvent) { + LifecycleState state = ((LifecycleEvent) e).getLifecycleState(); + if (state.isAfter(STARTING_SERVICES)) + runOnUiThreadUnlessDestroyed(this::finishAndStartApp); + else if (state == MIGRATING_DATABASE) + runOnUiThreadUnlessDestroyed(this::showMigration); + } + } + + private void showMigration() { + if (showingMigration) return; + textView.setText(R.string.startup_migrate_database); + imageView.setImageResource(R.drawable.startup_migration); + showingMigration = true; + } + + private void finishAndStartApp() { + startActivity(new Intent(this, NavDrawerActivity.class)); + supportFinishAfterTransition(); + } + +} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupActivity.java index 17c6f522f384d2bc68e7e5aa49905404f22d0d44..2b17df6eaf0f93d47b7234b728993e37000d0d40 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupActivity.java @@ -8,7 +8,6 @@ import org.briarproject.briar.R; import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.BaseActivity; import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener; -import org.briarproject.briar.android.navdrawer.NavDrawerActivity; import javax.inject.Inject; @@ -48,7 +47,7 @@ public class SetupActivity extends BaseActivity } public void showApp() { - Intent i = new Intent(this, NavDrawerActivity.class); + Intent i = new Intent(this, OpenDatabaseActivity.class); i.setFlags(FLAG_ACTIVITY_NEW_TASK); startActivity(i); supportFinishAfterTransition(); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java index d083343e91f329e01410c7d2e2a2d1ca7cac6ab5..dcc42f6c33cdb6ca8e795b023f5644d5594ed4e6 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java @@ -46,8 +46,6 @@ import java.util.logging.Logger; import javax.inject.Inject; -import static android.os.Build.MANUFACTURER; -import static android.os.Build.VERSION.SDK_INT; import static android.support.v4.app.FragmentManager.POP_BACK_STACK_INCLUSIVE; import static android.support.v4.view.GravityCompat.START; import static android.support.v4.widget.DrawerLayout.LOCK_MODE_LOCKED_CLOSED; @@ -214,18 +212,6 @@ public class NavDrawerActivity extends BriarActivity implements public void onBackPressed() { if (drawerLayout.isDrawerOpen(START)) { drawerLayout.closeDrawer(START); - } else if (getSupportFragmentManager().getBackStackEntryCount() == 0 && - getSupportFragmentManager() - .findFragmentByTag(ContactListFragment.TAG) != null) { - if (SDK_INT == 19 && MANUFACTURER.equalsIgnoreCase("Samsung")) { - // workaround for #1116 causes splash screen to show again - super.onBackPressed(); - } else { - Intent i = new Intent(Intent.ACTION_MAIN); - i.addCategory(Intent.CATEGORY_HOME); - i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(i); - } } else if (getSupportFragmentManager().getBackStackEntryCount() == 0 && getSupportFragmentManager() .findFragmentByTag(ContactListFragment.TAG) == null) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/splash/SplashScreenActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/splash/SplashScreenActivity.java index 7c19f3c780231ab3d2196a7875ef30e6cda226c7..f21f460aa17bcc17d27da0a3db4f9c9b6627f6b2 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/splash/SplashScreenActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/splash/SplashScreenActivity.java @@ -12,8 +12,8 @@ import org.briarproject.briar.R; import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.BaseActivity; import org.briarproject.briar.android.controller.ConfigController; +import org.briarproject.briar.android.login.OpenDatabaseActivity; import org.briarproject.briar.android.login.SetupActivity; -import org.briarproject.briar.android.navdrawer.NavDrawerActivity; import java.util.logging.Logger; @@ -43,10 +43,15 @@ public class SplashScreenActivity extends BaseActivity { setContentView(R.layout.splash); - new Handler().postDelayed(() -> { - startNextActivity(); - supportFinishAfterTransition(); - }, 500); + if (configController.accountSignedIn()) { + startActivity(new Intent(this, OpenDatabaseActivity.class)); + finish(); + } else { + new Handler().postDelayed(() -> { + startNextActivity(); + supportFinishAfterTransition(); + }, 500); + } } @Override @@ -60,7 +65,7 @@ public class SplashScreenActivity extends BaseActivity { startActivity(new Intent(this, ExpiredActivity.class)); } else { if (configController.accountExists()) { - startActivity(new Intent(this, NavDrawerActivity.class)); + startActivity(new Intent(this, OpenDatabaseActivity.class)); } else { configController.deleteAccount(this); startActivity(new Intent(this, SetupActivity.class)); diff --git a/briar-android/src/main/res/drawable/startup_lock.xml b/briar-android/src/main/res/drawable/startup_lock.xml new file mode 100644 index 0000000000000000000000000000000000000000..181a64cc9162141b4bfe208b94a70bf94d4b31da --- /dev/null +++ b/briar-android/src/main/res/drawable/startup_lock.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="64dp" + android:height="64dp" + android:viewportHeight="24.0" + android:viewportWidth="24.0"> + <path + android:fillColor="#FF000000" + android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z"/> +</vector> diff --git a/briar-android/src/main/res/drawable/startup_migration.xml b/briar-android/src/main/res/drawable/startup_migration.xml new file mode 100644 index 0000000000000000000000000000000000000000..a5021ef0dad493614ddb3e068540d5cf992d6e77 --- /dev/null +++ b/briar-android/src/main/res/drawable/startup_migration.xml @@ -0,0 +1,9 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="64dp" + android:height="64dp" + android:viewportHeight="24.0" + android:viewportWidth="24.0"> + <path + android:fillColor="#FF000000" + android:pathData="M21,10.12h-6.78l2.74,-2.82c-2.73,-2.7 -7.15,-2.8 -9.88,-0.1 -2.73,2.71 -2.73,7.08 0,9.79 2.73,2.71 7.15,2.71 9.88,0C18.32,15.65 19,14.08 19,12.1h2c0,1.98 -0.88,4.55 -2.64,6.29 -3.51,3.48 -9.21,3.48 -12.72,0 -3.5,-3.47 -3.53,-9.11 -0.02,-12.58 3.51,-3.47 9.14,-3.47 12.65,0L21,3v7.12zM12.5,8v4.25l3.5,2.08 -0.72,1.21L11,13V8h1.5z"/> +</vector> diff --git a/briar-android/src/main/res/layout/activity_open_database.xml b/briar-android/src/main/res/layout/activity_open_database.xml new file mode 100644 index 0000000000000000000000000000000000000000..ab20f17cb9dbb3a0924a9513f69f67a9f12e8b85 --- /dev/null +++ b/briar-android/src/main/res/layout/activity_open_database.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.constraint.ConstraintLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <ImageView + android:id="@+id/imageView" + android:layout_width="128dp" + android:layout_height="128dp" + android:scaleType="center" + android:src="@drawable/startup_lock" + android:tint="@color/briar_primary" + app:layout_constraintBottom_toTopOf="@+id/textView" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.5" + app:layout_constraintVertical_chainStyle="packed" + tools:ignore="ContentDescription"/> + + <ProgressBar + android:id="@+id/progressBar" + style="?android:attr/progressBarStyleLarge" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintBottom_toBottomOf="@+id/imageView" + app:layout_constraintEnd_toEndOf="@+id/imageView" + app:layout_constraintStart_toStartOf="@+id/imageView" + app:layout_constraintTop_toTopOf="@+id/imageView"/> + + <TextView + android:id="@+id/textView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="8dp" + android:text="@string/startup_open_database" + android:textSize="@dimen/text_size_large" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/imageView"/> + +</android.support.constraint.ConstraintLayout> \ No newline at end of file diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml index c682069f77c29abed6b07cb0a20e4b460e86ce90..14de9071b5dd7e220b2ed96e66999f29c6e197b2 100644 --- a/briar-android/src/main/res/values/strings.xml +++ b/briar-android/src/main/res/values/strings.xml @@ -46,6 +46,8 @@ </plurals> <string name="expiry_update">The testing expiry date has been extended. Your account will now expire in %d days.</string> <string name="expiry_date_reached">This software has expired.\nThank you for testing!</string> + <string name="startup_open_database">Decrypting Database…</string> + <string name="startup_migrate_database">Upgrading Database…</string> <!-- Navigation Drawer --> <string name="nav_drawer_open_description">Open the navigation drawer</string>