|
|
|
|
@ -39,6 +39,7 @@ import org.json.JSONException;
|
|
|
|
|
import org.thoughtcrime.securesms.attachments.Attachment;
|
|
|
|
|
import org.thoughtcrime.securesms.attachments.AttachmentId;
|
|
|
|
|
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
|
|
|
|
import org.thoughtcrime.securesms.attachments.DatabaseAttachmentAudioExtras;
|
|
|
|
|
import org.thoughtcrime.securesms.crypto.AttachmentSecret;
|
|
|
|
|
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream;
|
|
|
|
|
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream;
|
|
|
|
|
@ -105,6 +106,9 @@ public class AttachmentDatabase extends Database {
|
|
|
|
|
static final String CAPTION = "caption";
|
|
|
|
|
public static final String URL = "url";
|
|
|
|
|
public static final String DIRECTORY = "parts";
|
|
|
|
|
// audio/* mime type only related columns.
|
|
|
|
|
static final String AUDIO_VISUAL_SAMPLES = "audio_visual_samples"; // Small amount of audio byte samples to visualise the content (e.g. draw waveform)
|
|
|
|
|
static final String AUDIO_DURATION = "audio_duration"; // Duration of the audio track in milliseconds.
|
|
|
|
|
|
|
|
|
|
public static final int TRANSFER_PROGRESS_DONE = 0;
|
|
|
|
|
public static final int TRANSFER_PROGRESS_STARTED = 1;
|
|
|
|
|
@ -112,6 +116,7 @@ public class AttachmentDatabase extends Database {
|
|
|
|
|
public static final int TRANSFER_PROGRESS_FAILED = 3;
|
|
|
|
|
|
|
|
|
|
private static final String PART_ID_WHERE = ROW_ID + " = ? AND " + UNIQUE_ID + " = ?";
|
|
|
|
|
private static final String PART_AUDIO_ONLY_WHERE = CONTENT_TYPE + " LIKE audio/%";
|
|
|
|
|
|
|
|
|
|
private static final String[] PROJECTION = new String[] {ROW_ID,
|
|
|
|
|
MMS_ID, CONTENT_TYPE, NAME, CONTENT_DISPOSITION,
|
|
|
|
|
@ -121,6 +126,8 @@ public class AttachmentDatabase extends Database {
|
|
|
|
|
QUOTE, DATA_RANDOM, THUMBNAIL_RANDOM, WIDTH, HEIGHT,
|
|
|
|
|
CAPTION, STICKER_PACK_ID, STICKER_PACK_KEY, STICKER_ID, URL};
|
|
|
|
|
|
|
|
|
|
private static final String[] PROJECTION_AUDIO_EXTRAS = new String[] {AUDIO_VISUAL_SAMPLES, AUDIO_DURATION};
|
|
|
|
|
|
|
|
|
|
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ROW_ID + " INTEGER PRIMARY KEY, " +
|
|
|
|
|
MMS_ID + " INTEGER, " + "seq" + " INTEGER DEFAULT 0, " +
|
|
|
|
|
CONTENT_TYPE + " TEXT, " + NAME + " TEXT, " + "chset" + " INTEGER, " +
|
|
|
|
|
@ -133,7 +140,8 @@ public class AttachmentDatabase extends Database {
|
|
|
|
|
VOICE_NOTE + " INTEGER DEFAULT 0, " + DATA_RANDOM + " BLOB, " + THUMBNAIL_RANDOM + " BLOB, " +
|
|
|
|
|
QUOTE + " INTEGER DEFAULT 0, " + WIDTH + " INTEGER DEFAULT 0, " + HEIGHT + " INTEGER DEFAULT 0, " +
|
|
|
|
|
CAPTION + " TEXT DEFAULT NULL, " + URL + " TEXT, " + STICKER_PACK_ID + " TEXT DEFAULT NULL, " +
|
|
|
|
|
STICKER_PACK_KEY + " DEFAULT NULL, " + STICKER_ID + " INTEGER DEFAULT -1);";
|
|
|
|
|
STICKER_PACK_KEY + " DEFAULT NULL, " + STICKER_ID + " INTEGER DEFAULT -1," +
|
|
|
|
|
AUDIO_VISUAL_SAMPLES + " BLOB, " + AUDIO_DURATION + " INTEGER);";
|
|
|
|
|
|
|
|
|
|
public static final String[] CREATE_INDEXS = {
|
|
|
|
|
"CREATE INDEX IF NOT EXISTS part_mms_id_index ON " + TABLE_NAME + " (" + MMS_ID + ");",
|
|
|
|
|
@ -822,6 +830,47 @@ public class AttachmentDatabase extends Database {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Retrieves the audio extra values associated with the attachment. Only "audio/*" mime type attachments are accepted.
|
|
|
|
|
* @return the related audio extras or null in case any of the audio extra columns are empty or the attachment is not an audio.
|
|
|
|
|
*/
|
|
|
|
|
public @Nullable DatabaseAttachmentAudioExtras getAttachmentAudioExtras(@NonNull AttachmentId attachmentId) {
|
|
|
|
|
try (Cursor cursor = databaseHelper.getReadableDatabase()
|
|
|
|
|
// We expect all the audio extra values to be present (not null) or reject the whole record.
|
|
|
|
|
.query(TABLE_NAME,
|
|
|
|
|
PROJECTION_AUDIO_EXTRAS,
|
|
|
|
|
PART_ID_WHERE +
|
|
|
|
|
" AND " + AUDIO_VISUAL_SAMPLES + " IS NOT NULL" +
|
|
|
|
|
" AND " + AUDIO_DURATION + " IS NOT NULL" +
|
|
|
|
|
" AND " + PART_AUDIO_ONLY_WHERE,
|
|
|
|
|
attachmentId.toStrings(),
|
|
|
|
|
null, null, null, "1")) {
|
|
|
|
|
|
|
|
|
|
if (cursor == null || !cursor.moveToFirst()) return null;
|
|
|
|
|
|
|
|
|
|
byte[] audioSamples = cursor.getBlob(cursor.getColumnIndexOrThrow(AUDIO_VISUAL_SAMPLES));
|
|
|
|
|
long duration = cursor.getLong(cursor.getColumnIndexOrThrow(AUDIO_DURATION));
|
|
|
|
|
|
|
|
|
|
return new DatabaseAttachmentAudioExtras(attachmentId, audioSamples, duration);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Updates audio extra columns for the "audio/*" mime type attachments only.
|
|
|
|
|
* @return true if the update operation was successful.
|
|
|
|
|
*/
|
|
|
|
|
public boolean setAttachmentAudioExtras(@NonNull DatabaseAttachmentAudioExtras extras) {
|
|
|
|
|
ContentValues values = new ContentValues();
|
|
|
|
|
values.put(AUDIO_VISUAL_SAMPLES, extras.getVisualSamples());
|
|
|
|
|
values.put(AUDIO_DURATION, extras.getDurationMs());
|
|
|
|
|
|
|
|
|
|
int alteredRows = databaseHelper.getWritableDatabase().update(TABLE_NAME,
|
|
|
|
|
values,
|
|
|
|
|
PART_ID_WHERE + " AND " + PART_AUDIO_ONLY_WHERE,
|
|
|
|
|
extras.getAttachmentId().toStrings());
|
|
|
|
|
|
|
|
|
|
return alteredRows > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@VisibleForTesting
|
|
|
|
|
class ThumbnailFetchCallable implements Callable<InputStream> {
|
|
|
|
|
|