save last activation time in fingerprint status

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java     | 18 
src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java  | 30 
src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java |  1 
src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java |  7 
src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java       | 10 
5 files changed, 58 insertions(+), 8 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java 🔗

@@ -25,7 +25,11 @@ import java.security.PrivateKey;
 import java.security.Security;
 import java.security.Signature;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -296,16 +300,20 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 		return new AxolotlAddress(jid.toPreppedString(), 0);
 	}
 
-	public Set<XmppAxolotlSession> findOwnSessions() {
+	public Collection<XmppAxolotlSession> findOwnSessions() {
 		AxolotlAddress ownAddress = getAddressForJid(account.getJid().toBareJid());
-		return new HashSet<>(this.sessions.getAll(ownAddress).values());
+		ArrayList<XmppAxolotlSession> s = new ArrayList<>(this.sessions.getAll(ownAddress).values());
+		Collections.sort(s);
+		return s;
 	}
 
 
 
-	public Set<XmppAxolotlSession> findSessionsForContact(Contact contact) {
+	public Collection<XmppAxolotlSession> findSessionsForContact(Contact contact) {
 		AxolotlAddress contactAddress = getAddressForJid(contact.getJid());
-		return new HashSet<>(this.sessions.getAll(contactAddress).values());
+		ArrayList<XmppAxolotlSession> s = new ArrayList<>(this.sessions.getAll(contactAddress).values());
+		Collections.sort(s);
+		return s;
 	}
 
 	private Set<XmppAxolotlSession> findSessionsForConversation(Conversation conversation) {
@@ -932,7 +940,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 				account.getJid().toBareJid(), getOwnDeviceId());
 
 		Set<XmppAxolotlSession> remoteSessions = findSessionsForConversation(conversation);
-		Set<XmppAxolotlSession> ownSessions = findOwnSessions();
+		Collection<XmppAxolotlSession> ownSessions = findOwnSessions();
 		if (remoteSessions.isEmpty()) {
 			return null;
 		}

src/main/java/eu/siacs/conversations/crypto/axolotl/FingerprintStatus.java 🔗

@@ -3,10 +3,13 @@ package eu.siacs.conversations.crypto.axolotl;
 import android.content.ContentValues;
 import android.database.Cursor;
 
-public class FingerprintStatus {
+public class FingerprintStatus implements Comparable<FingerprintStatus> {
+
+    private static final long DO_NOT_OVERWRITE = -1;
 
     private Trust trust = Trust.UNTRUSTED;
     private boolean active = false;
+    private long lastActivation = DO_NOT_OVERWRITE;
 
     @Override
     public boolean equals(Object o) {
@@ -34,6 +37,9 @@ public class FingerprintStatus {
         final ContentValues contentValues = new ContentValues();
         contentValues.put(SQLiteAxolotlStore.TRUST,trust.toString());
         contentValues.put(SQLiteAxolotlStore.ACTIVE,active ? 1 : 0);
+        if (lastActivation != DO_NOT_OVERWRITE) {
+            contentValues.put(SQLiteAxolotlStore.LAST_ACTIVATION,lastActivation);
+        }
         return contentValues;
     }
 
@@ -45,6 +51,7 @@ public class FingerprintStatus {
             status.trust = Trust.UNTRUSTED;
         }
         status.active = cursor.getInt(cursor.getColumnIndex(SQLiteAxolotlStore.ACTIVE)) > 0;
+        status.lastActivation = cursor.getLong(cursor.getColumnIndex(SQLiteAxolotlStore.LAST_ACTIVATION));
         return status;
     }
 
@@ -52,6 +59,7 @@ public class FingerprintStatus {
         final FingerprintStatus status = new FingerprintStatus();
         status.trust = Trust.UNDECIDED;
         status.active = true;
+        status.lastActivation = System.currentTimeMillis();
         return status;
     }
 
@@ -92,6 +100,9 @@ public class FingerprintStatus {
     public FingerprintStatus toActive() {
         FingerprintStatus status = new FingerprintStatus();
         status.trust = trust;
+        if (!status.active) {
+            status.lastActivation = System.currentTimeMillis();
+        }
         status.active = true;
         return status;
     }
@@ -128,6 +139,23 @@ public class FingerprintStatus {
         return status;
     }
 
+    @Override
+    public int compareTo(FingerprintStatus o) {
+        if (active == o.active) {
+            if (lastActivation > o.lastActivation) {
+                return -1;
+            } else if (lastActivation < o.lastActivation) {
+                return 1;
+            } else {
+                return 0;
+            }
+        } else if (active){
+            return -1;
+        } else {
+            return 1;
+        }
+    }
+
     public enum Trust {
         COMPROMISED,
         UNDECIDED,

src/main/java/eu/siacs/conversations/crypto/axolotl/SQLiteAxolotlStore.java 🔗

@@ -38,6 +38,7 @@ public class SQLiteAxolotlStore implements AxolotlStore {
 	public static final String TRUSTED = "trusted"; //no longer used
 	public static final String TRUST = "trust";
 	public static final String ACTIVE = "active";
+	public static final String LAST_ACTIVATION = "last_activation";
 	public static final String OWN = "ownkey";
 	public static final String CERTIFICATE = "certificate";
 

src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlSession.java 🔗

@@ -22,7 +22,7 @@ import org.whispersystems.libaxolotl.protocol.WhisperMessage;
 import eu.siacs.conversations.Config;
 import eu.siacs.conversations.entities.Account;
 
-public class XmppAxolotlSession {
+public class XmppAxolotlSession implements Comparable<XmppAxolotlSession> {
 	private final SessionCipher cipher;
 	private final SQLiteAxolotlStore sqLiteAxolotlStore;
 	private final AxolotlAddress remoteAddress;
@@ -136,4 +136,9 @@ public class XmppAxolotlSession {
 	public Account getAccount() {
 		return account;
 	}
+
+	@Override
+	public int compareTo(XmppAxolotlSession o) {
+		return getTrust().compareTo(o.getTrust());
+	}
 }

src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java 🔗

@@ -55,7 +55,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 	private static DatabaseBackend instance = null;
 
 	private static final String DATABASE_NAME = "history";
-	private static final int DATABASE_VERSION = 31;
+	private static final int DATABASE_VERSION = 32;
 
 	private static String CREATE_CONTATCS_STATEMENT = "create table "
 			+ Contact.TABLENAME + "(" + Contact.ACCOUNT + " TEXT, "
@@ -132,6 +132,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 			+ SQLiteAxolotlStore.CERTIFICATE + " BLOB, "
 			+ SQLiteAxolotlStore.TRUST + " TEXT, "
 			+ SQLiteAxolotlStore.ACTIVE + " NUMBER, "
+			+ SQLiteAxolotlStore.LAST_ACTIVATION + " NUMBER,"
 			+ SQLiteAxolotlStore.KEY + " TEXT, FOREIGN KEY("
 			+ SQLiteAxolotlStore.ACCOUNT
 			+ ") REFERENCES " + Account.TABLENAME + "(" + Account.UUID + ") ON DELETE CASCADE, "
@@ -377,6 +378,12 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 			}
 
 		}
+		if (oldVersion < 32 && newVersion >= 32) {
+			db.execSQL("ALTER TABLE "+ SQLiteAxolotlStore.IDENTITIES_TABLENAME + " ADD COLUMN "+SQLiteAxolotlStore.LAST_ACTIVATION + " NUMBER");
+			ContentValues defaults = new ContentValues();
+			defaults.put(SQLiteAxolotlStore.LAST_ACTIVATION,System.currentTimeMillis());
+			db.update(SQLiteAxolotlStore.IDENTITIES_TABLENAME,defaults,null,null);
+		}
 	}
 
 	private static ContentValues createFingerprintStatusContentValues(FingerprintStatus.Trust trust, boolean active) {
@@ -1046,6 +1053,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
 	private Cursor getIdentityKeyCursor(SQLiteDatabase db, Account account, String name, Boolean own, String fingerprint) {
 		String[] columns = {SQLiteAxolotlStore.TRUST,
 				SQLiteAxolotlStore.ACTIVE,
+				SQLiteAxolotlStore.LAST_ACTIVATION,
 				SQLiteAxolotlStore.KEY};
 		ArrayList<String> selectionArgs = new ArrayList<>(4);
 		selectionArgs.add(account.getUuid());