diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7912ab9739..4e3e3a8b6e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -399,12 +399,6 @@ - - - - - @@ -438,17 +432,9 @@ - - diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index e10a7a7dc7..8f561f6314 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -56,7 +56,6 @@ import org.signal.aesgcmprovider.AesGcmProvider; import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.crypto.KeyPairUtilities; import org.thoughtcrime.securesms.database.EmojiSearchDatabase; -import org.thoughtcrime.securesms.database.JobDatabase; import org.thoughtcrime.securesms.database.LokiAPIDatabase; import org.thoughtcrime.securesms.database.Storage; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; @@ -66,11 +65,7 @@ import org.thoughtcrime.securesms.dependencies.DatabaseModule; import org.thoughtcrime.securesms.emoji.EmojiSource; import org.thoughtcrime.securesms.groups.OpenGroupManager; import org.thoughtcrime.securesms.home.HomeActivity; -import org.thoughtcrime.securesms.jobmanager.JobManager; -import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer; import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.thoughtcrime.securesms.jobs.FastJobStorage; -import org.thoughtcrime.securesms.jobs.JobManagerFactories; import org.thoughtcrime.securesms.logging.AndroidLogger; import org.thoughtcrime.securesms.logging.PersistentLogger; import org.thoughtcrime.securesms.logging.UncaughtExceptionLogger; @@ -111,7 +106,6 @@ import dagger.hilt.EntryPoints; import dagger.hilt.android.HiltAndroidApp; import kotlin.Unit; import kotlinx.coroutines.Job; -import network.loki.messenger.BuildConfig; /** * Will be called once when the TextSecure process is created. @@ -131,7 +125,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO private ExpiringMessageManager expiringMessageManager; private TypingStatusRepository typingStatusRepository; private TypingStatusSender typingStatusSender; - private JobManager jobManager; private ReadReceiptManager readReceiptManager; private ProfileManager profileManager; public MessageNotifier messageNotifier = null; @@ -146,7 +139,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO @Inject LokiAPIDatabase lokiAPIDatabase; @Inject Storage storage; @Inject MessageDataProvider messageDataProvider; - @Inject JobDatabase jobDatabase; @Inject TextSecurePreferences textSecurePreferences; @Inject PushManager pushManager; CallMessageProcessor callMessageProcessor; @@ -166,10 +158,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO return (ApplicationContext) context.getApplicationContext(); } - public TextSecurePreferences getPrefs() { - return textSecurePreferences; - } - public DatabaseComponent getDatabaseComponent() { return EntryPoints.get(getApplicationContext(), DatabaseComponent.class); } @@ -225,7 +213,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO initializeProfileManager(); initializePeriodicTasks(); SSKEnvironment.Companion.configure(getTypingStatusRepository(), getReadReceiptManager(), getProfileManager(), messageNotifier, getExpiringMessageManager()); - initializeJobManager(); initializeWebRtc(); initializeBlobProvider(); resubmitProfilePictureIfNeeded(); @@ -282,10 +269,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO LocaleParser.Companion.configure(new LocaleParseHelper()); } - public JobManager getJobManager() { - return jobManager; - } - public ExpiringMessageManager getExpiringMessageManager() { return expiringMessageManager; } @@ -348,16 +331,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionLogger(originalHandler)); } - private void initializeJobManager() { - this.jobManager = new JobManager(this, new JobManager.Configuration.Builder() - .setDataSerializer(new JsonDataSerializer()) - .setJobFactories(JobManagerFactories.getJobFactories(this)) - .setConstraintFactories(JobManagerFactories.getConstraintFactories(this)) - .setConstraintObservers(JobManagerFactories.getConstraintObservers(this)) - .setJobStorage(new FastJobStorage(jobDatabase)) - .build()); - } - private void initializeExpiringMessageManager() { this.expiringMessageManager = new ExpiringMessageManager(this); } @@ -380,10 +353,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO private void initializePeriodicTasks() { BackgroundPollWorker.schedulePeriodic(this); - - if (BuildConfig.PLAY_STORE_DISABLED) { - // possibly add update apk job - } } private void initializeWebRtc() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java b/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java index 7d82c760cc..51f66ec323 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java @@ -1,5 +1,6 @@ package org.thoughtcrime.securesms; +import static android.os.Build.VERSION.SDK_INT; import static org.session.libsession.utilities.TextSecurePreferences.SELECTED_ACCENT_COLOR; import android.app.ActivityManager; @@ -18,6 +19,7 @@ import androidx.appcompat.app.AppCompatActivity; import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageActivityHelper; import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper; +import org.thoughtcrime.securesms.conversation.v2.WindowUtil; import org.thoughtcrime.securesms.util.ActivityUtilitiesKt; import org.thoughtcrime.securesms.util.ThemeState; import org.thoughtcrime.securesms.util.UiModeUtilities; @@ -92,6 +94,11 @@ public abstract class BaseActionBarActivity extends AppCompatActivity { if (!currentThemeState.equals(ActivityUtilitiesKt.themeState(getPreferences()))) { recreate(); } + + // apply lightStatusBar manually as API 26 does not update properly via applyTheme + // https://issuetracker.google.com/issues/65883460?pli=1 + if (SDK_INT >= 26 && SDK_INT <= 27) WindowUtil.setLightStatusBarFromTheme(this); + if (SDK_INT == 27) WindowUtil.setLightNavigationBarFromTheme(this); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/attachments/ScreenshotObserver.kt b/app/src/main/java/org/thoughtcrime/securesms/attachments/ScreenshotObserver.kt index 84a9b6cfc3..9c7ca21e8b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/attachments/ScreenshotObserver.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/attachments/ScreenshotObserver.kt @@ -7,6 +7,10 @@ import android.os.Build import android.os.Handler import android.provider.MediaStore import androidx.annotation.RequiresApi +import org.session.libsignal.utilities.Log +import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer + +private const val TAG = "ScreenshotObserver" class ScreenshotObserver(private val context: Context, handler: Handler, private val screenshotTriggered: ()->Unit): ContentObserver(handler) { @@ -31,22 +35,26 @@ class ScreenshotObserver(private val context: Context, handler: Handler, private val projection = arrayOf( MediaStore.Images.Media.DATA ) - context.contentResolver.query( - uri, - projection, - null, - null, - null - )?.use { cursor -> - val dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA) - while (cursor.moveToNext()) { - val path = cursor.getString(dataColumn) - if (path.contains("screenshot", true)) { - if (cache.add(uri.hashCode())) { - screenshotTriggered() + try { + context.contentResolver.query( + uri, + projection, + null, + null, + null + )?.use { cursor -> + val dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA) + while (cursor.moveToNext()) { + val path = cursor.getString(dataColumn) + if (path.contains("screenshot", true)) { + if (cache.add(uri.hashCode())) { + screenshotTriggered() + } } } } + } catch (e: SecurityException) { + Log.e(TAG, e) } } @@ -56,28 +64,32 @@ class ScreenshotObserver(private val context: Context, handler: Handler, private MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.RELATIVE_PATH ) - context.contentResolver.query( - uri, - projection, - null, - null, - null - )?.use { cursor -> - val relativePathColumn = - cursor.getColumnIndex(MediaStore.Images.Media.RELATIVE_PATH) - val displayNameColumn = - cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME) - while (cursor.moveToNext()) { - val name = cursor.getString(displayNameColumn) - val relativePath = cursor.getString(relativePathColumn) - if (name.contains("screenshot", true) or - relativePath.contains("screenshot", true)) { - if (cache.add(uri.hashCode())) { - screenshotTriggered() + + try { + context.contentResolver.query( + uri, + projection, + null, + null, + null + )?.use { cursor -> + val relativePathColumn = + cursor.getColumnIndex(MediaStore.Images.Media.RELATIVE_PATH) + val displayNameColumn = + cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME) + while (cursor.moveToNext()) { + val name = cursor.getString(displayNameColumn) + val relativePath = cursor.getString(relativePathColumn) + if (name.contains("screenshot", true) or + relativePath.contains("screenshot", true)) { + if (cache.add(uri.hashCode())) { + screenshotTriggered() + } } } } + } catch (e: IllegalStateException) { + Log.e(TAG, e) } } - -} \ No newline at end of file +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupEvent.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/BackupEvent.kt deleted file mode 100644 index 614dc30bba..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupEvent.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.thoughtcrime.securesms.backup - -data class BackupEvent constructor(val type: Type, val count: Int, val exception: Exception?) { - - enum class Type { - PROGRESS, FINISHED - } - - companion object { - @JvmStatic fun createProgress(count: Int) = BackupEvent(Type.PROGRESS, count, null) - @JvmStatic fun createFinished() = BackupEvent(Type.FINISHED, 0, null) - @JvmStatic fun createFinished(e: Exception?) = BackupEvent(Type.FINISHED, 0, e) - } -} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupPassphrase.java b/app/src/main/java/org/thoughtcrime/securesms/backup/BackupPassphrase.java deleted file mode 100644 index eec2a2e588..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupPassphrase.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.thoughtcrime.securesms.backup; - -import android.content.Context; -import android.os.Build; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.thoughtcrime.securesms.crypto.KeyStoreHelper; -import org.session.libsignal.utilities.Log; -import org.session.libsession.utilities.TextSecurePreferences; - -/** - * Allows the getting and setting of the backup passphrase, which is stored encrypted on API >= 23. - */ -public class BackupPassphrase { - - private static final String TAG = BackupPassphrase.class.getSimpleName(); - - public static @Nullable String get(@NonNull Context context) { - String passphrase = TextSecurePreferences.getBackupPassphrase(context); - String encryptedPassphrase = TextSecurePreferences.getEncryptedBackupPassphrase(context); - - if (Build.VERSION.SDK_INT < 23 || (passphrase == null && encryptedPassphrase == null)) { - return passphrase; - } - - if (encryptedPassphrase == null) { - Log.i(TAG, "Migrating to encrypted passphrase."); - set(context, passphrase); - encryptedPassphrase = TextSecurePreferences.getEncryptedBackupPassphrase(context); - } - - KeyStoreHelper.SealedData data = KeyStoreHelper.SealedData.fromString(encryptedPassphrase); - return new String(KeyStoreHelper.unseal(data)); - } - - public static void set(@NonNull Context context, @Nullable String passphrase) { - if (passphrase == null || Build.VERSION.SDK_INT < 23) { - TextSecurePreferences.setBackupPassphrase(context, passphrase); - TextSecurePreferences.setEncryptedBackupPassphrase(context, null); - } else { - KeyStoreHelper.SealedData encryptedPassphrase = KeyStoreHelper.seal(passphrase.getBytes()); - TextSecurePreferences.setEncryptedBackupPassphrase(context, encryptedPassphrase.serialize()); - TextSecurePreferences.setBackupPassphrase(context, null); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupPreferences.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/BackupPreferences.kt deleted file mode 100644 index 8ddfc23a8b..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupPreferences.kt +++ /dev/null @@ -1,101 +0,0 @@ -package org.thoughtcrime.securesms.backup - -import android.content.Context -import android.content.SharedPreferences -import android.os.Build -import android.preference.PreferenceManager -import android.preference.PreferenceManager.getDefaultSharedPreferencesName -import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsignal.utilities.Log -import org.thoughtcrime.securesms.backup.FullBackupImporter.PREF_PREFIX_TYPE_BOOLEAN -import org.thoughtcrime.securesms.backup.FullBackupImporter.PREF_PREFIX_TYPE_INT -import java.util.* - -object BackupPreferences { - // region Backup related - fun getBackupRecords(context: Context): List { - val preferences = PreferenceManager.getDefaultSharedPreferences(context) - val prefsFileName: String - prefsFileName = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - getDefaultSharedPreferencesName(context) - } else { - context.packageName + "_preferences" - } - val prefList: LinkedList = LinkedList() - addBackupEntryInt(prefList, preferences, prefsFileName, TextSecurePreferences.LOCAL_REGISTRATION_ID_PREF) - addBackupEntryString(prefList, preferences, prefsFileName, TextSecurePreferences.LOCAL_NUMBER_PREF) - addBackupEntryString(prefList, preferences, prefsFileName, TextSecurePreferences.PROFILE_NAME_PREF) - addBackupEntryString(prefList, preferences, prefsFileName, TextSecurePreferences.PROFILE_AVATAR_URL_PREF) - addBackupEntryInt(prefList, preferences, prefsFileName, TextSecurePreferences.PROFILE_AVATAR_ID_PREF) - addBackupEntryString(prefList, preferences, prefsFileName, TextSecurePreferences.PROFILE_KEY_PREF) - addBackupEntryBoolean(prefList, preferences, prefsFileName, TextSecurePreferences.IS_USING_FCM) - return prefList - } - - private fun addBackupEntryString( - outPrefList: MutableList, - prefs: SharedPreferences, - prefFileName: String, - prefKey: String, - ) { - val value = prefs.getString(prefKey, null) - if (value == null) { - logBackupEntry(prefKey, false) - return - } - outPrefList.add(BackupProtos.SharedPreference.newBuilder() - .setFile(prefFileName) - .setKey(prefKey) - .setValue(value) - .build()) - logBackupEntry(prefKey, true) - } - - private fun addBackupEntryInt( - outPrefList: MutableList, - prefs: SharedPreferences, - prefFileName: String, - prefKey: String, - ) { - val value = prefs.getInt(prefKey, -1) - if (value == -1) { - logBackupEntry(prefKey, false) - return - } - outPrefList.add(BackupProtos.SharedPreference.newBuilder() - .setFile(prefFileName) - .setKey(PREF_PREFIX_TYPE_INT + prefKey) // The prefix denotes the type of the preference. - .setValue(value.toString()) - .build()) - logBackupEntry(prefKey, true) - } - - private fun addBackupEntryBoolean( - outPrefList: MutableList, - prefs: SharedPreferences, - prefFileName: String, - prefKey: String, - ) { - if (!prefs.contains(prefKey)) { - logBackupEntry(prefKey, false) - return - } - outPrefList.add(BackupProtos.SharedPreference.newBuilder() - .setFile(prefFileName) - .setKey(PREF_PREFIX_TYPE_BOOLEAN + prefKey) // The prefix denotes the type of the preference. - .setValue(prefs.getBoolean(prefKey, false).toString()) - .build()) - logBackupEntry(prefKey, true) - } - - private fun logBackupEntry(prefName: String, wasIncluded: Boolean) { - val sb = StringBuilder() - sb.append("Backup preference ") - sb.append(if (wasIncluded) "+ " else "- ") - sb.append('\"').append(prefName).append("\" ") - if (!wasIncluded) { - sb.append("(is empty and not included)") - } - Log.d("Loki", sb.toString()) - } // endregion -} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupProtos.java b/app/src/main/java/org/thoughtcrime/securesms/backup/BackupProtos.java deleted file mode 100644 index f3b78606f4..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/BackupProtos.java +++ /dev/null @@ -1,6778 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: Backups.proto - -package org.thoughtcrime.securesms.backup; - -public final class BackupProtos { - private BackupProtos() {} - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - } - public interface SqlStatementOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // optional string statement = 1; - /** - * optional string statement = 1; - */ - boolean hasStatement(); - /** - * optional string statement = 1; - */ - java.lang.String getStatement(); - /** - * optional string statement = 1; - */ - com.google.protobuf.ByteString - getStatementBytes(); - - // repeated .signal.SqlStatement.SqlParameter parameters = 2; - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - java.util.List - getParametersList(); - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter getParameters(int index); - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - int getParametersCount(); - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - java.util.List - getParametersOrBuilderList(); - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder getParametersOrBuilder( - int index); - } - /** - * Protobuf type {@code signal.SqlStatement} - */ - public static final class SqlStatement extends - com.google.protobuf.GeneratedMessage - implements SqlStatementOrBuilder { - // Use SqlStatement.newBuilder() to construct. - private SqlStatement(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - this.unknownFields = builder.getUnknownFields(); - } - private SqlStatement(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } - - private static final SqlStatement defaultInstance; - public static SqlStatement getDefaultInstance() { - return defaultInstance; - } - - public SqlStatement getDefaultInstanceForType() { - return defaultInstance; - } - - private final com.google.protobuf.UnknownFieldSet unknownFields; - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private SqlStatement( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - initFields(); - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - done = true; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - statement_ = input.readBytes(); - break; - } - case 18: { - if (!((mutable_bitField0_ & 0x00000002) == 0x00000002)) { - parameters_ = new java.util.ArrayList(); - mutable_bitField0_ |= 0x00000002; - } - parameters_.add(input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.PARSER, extensionRegistry)); - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e.getMessage()).setUnfinishedMessage(this); - } finally { - if (((mutable_bitField0_ & 0x00000002) == 0x00000002)) { - parameters_ = java.util.Collections.unmodifiableList(parameters_); - } - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.class, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder.class); - } - - public static com.google.protobuf.Parser PARSER = - new com.google.protobuf.AbstractParser() { - public SqlStatement parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new SqlStatement(input, extensionRegistry); - } - }; - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - public interface SqlParameterOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // optional string stringParamter = 1; - /** - * optional string stringParamter = 1; - */ - boolean hasStringParamter(); - /** - * optional string stringParamter = 1; - */ - java.lang.String getStringParamter(); - /** - * optional string stringParamter = 1; - */ - com.google.protobuf.ByteString - getStringParamterBytes(); - - // optional uint64 integerParameter = 2; - /** - * optional uint64 integerParameter = 2; - */ - boolean hasIntegerParameter(); - /** - * optional uint64 integerParameter = 2; - */ - long getIntegerParameter(); - - // optional double doubleParameter = 3; - /** - * optional double doubleParameter = 3; - */ - boolean hasDoubleParameter(); - /** - * optional double doubleParameter = 3; - */ - double getDoubleParameter(); - - // optional bytes blobParameter = 4; - /** - * optional bytes blobParameter = 4; - */ - boolean hasBlobParameter(); - /** - * optional bytes blobParameter = 4; - */ - com.google.protobuf.ByteString getBlobParameter(); - - // optional bool nullparameter = 5; - /** - * optional bool nullparameter = 5; - */ - boolean hasNullparameter(); - /** - * optional bool nullparameter = 5; - */ - boolean getNullparameter(); - } - /** - * Protobuf type {@code signal.SqlStatement.SqlParameter} - */ - public static final class SqlParameter extends - com.google.protobuf.GeneratedMessage - implements SqlParameterOrBuilder { - // Use SqlParameter.newBuilder() to construct. - private SqlParameter(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - this.unknownFields = builder.getUnknownFields(); - } - private SqlParameter(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } - - private static final SqlParameter defaultInstance; - public static SqlParameter getDefaultInstance() { - return defaultInstance; - } - - public SqlParameter getDefaultInstanceForType() { - return defaultInstance; - } - - private final com.google.protobuf.UnknownFieldSet unknownFields; - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private SqlParameter( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - initFields(); - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - done = true; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - stringParamter_ = input.readBytes(); - break; - } - case 16: { - bitField0_ |= 0x00000002; - integerParameter_ = input.readUInt64(); - break; - } - case 25: { - bitField0_ |= 0x00000004; - doubleParameter_ = input.readDouble(); - break; - } - case 34: { - bitField0_ |= 0x00000008; - blobParameter_ = input.readBytes(); - break; - } - case 40: { - bitField0_ |= 0x00000010; - nullparameter_ = input.readBool(); - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e.getMessage()).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_SqlParameter_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_SqlParameter_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.class, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder.class); - } - - public static com.google.protobuf.Parser PARSER = - new com.google.protobuf.AbstractParser() { - public SqlParameter parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new SqlParameter(input, extensionRegistry); - } - }; - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - private int bitField0_; - // optional string stringParamter = 1; - public static final int STRINGPARAMTER_FIELD_NUMBER = 1; - private java.lang.Object stringParamter_; - /** - * optional string stringParamter = 1; - */ - public boolean hasStringParamter() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional string stringParamter = 1; - */ - public java.lang.String getStringParamter() { - java.lang.Object ref = stringParamter_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - stringParamter_ = s; - } - return s; - } - } - /** - * optional string stringParamter = 1; - */ - public com.google.protobuf.ByteString - getStringParamterBytes() { - java.lang.Object ref = stringParamter_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - stringParamter_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // optional uint64 integerParameter = 2; - public static final int INTEGERPARAMETER_FIELD_NUMBER = 2; - private long integerParameter_; - /** - * optional uint64 integerParameter = 2; - */ - public boolean hasIntegerParameter() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional uint64 integerParameter = 2; - */ - public long getIntegerParameter() { - return integerParameter_; - } - - // optional double doubleParameter = 3; - public static final int DOUBLEPARAMETER_FIELD_NUMBER = 3; - private double doubleParameter_; - /** - * optional double doubleParameter = 3; - */ - public boolean hasDoubleParameter() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - /** - * optional double doubleParameter = 3; - */ - public double getDoubleParameter() { - return doubleParameter_; - } - - // optional bytes blobParameter = 4; - public static final int BLOBPARAMETER_FIELD_NUMBER = 4; - private com.google.protobuf.ByteString blobParameter_; - /** - * optional bytes blobParameter = 4; - */ - public boolean hasBlobParameter() { - return ((bitField0_ & 0x00000008) == 0x00000008); - } - /** - * optional bytes blobParameter = 4; - */ - public com.google.protobuf.ByteString getBlobParameter() { - return blobParameter_; - } - - // optional bool nullparameter = 5; - public static final int NULLPARAMETER_FIELD_NUMBER = 5; - private boolean nullparameter_; - /** - * optional bool nullparameter = 5; - */ - public boolean hasNullparameter() { - return ((bitField0_ & 0x00000010) == 0x00000010); - } - /** - * optional bool nullparameter = 5; - */ - public boolean getNullparameter() { - return nullparameter_; - } - - private void initFields() { - stringParamter_ = ""; - integerParameter_ = 0L; - doubleParameter_ = 0D; - blobParameter_ = com.google.protobuf.ByteString.EMPTY; - nullparameter_ = false; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getStringParamterBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeUInt64(2, integerParameter_); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeDouble(3, doubleParameter_); - } - if (((bitField0_ & 0x00000008) == 0x00000008)) { - output.writeBytes(4, blobParameter_); - } - if (((bitField0_ & 0x00000010) == 0x00000010)) { - output.writeBool(5, nullparameter_); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getStringParamterBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeUInt64Size(2, integerParameter_); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - size += com.google.protobuf.CodedOutputStream - .computeDoubleSize(3, doubleParameter_); - } - if (((bitField0_ & 0x00000008) == 0x00000008)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(4, blobParameter_); - } - if (((bitField0_ & 0x00000010) == 0x00000010)) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(5, nullparameter_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code signal.SqlStatement.SqlParameter} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_SqlParameter_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_SqlParameter_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.class, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder.class); - } - - // Construct using org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - stringParamter_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - integerParameter_ = 0L; - bitField0_ = (bitField0_ & ~0x00000002); - doubleParameter_ = 0D; - bitField0_ = (bitField0_ & ~0x00000004); - blobParameter_ = com.google.protobuf.ByteString.EMPTY; - bitField0_ = (bitField0_ & ~0x00000008); - nullparameter_ = false; - bitField0_ = (bitField0_ & ~0x00000010); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_SqlParameter_descriptor; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter getDefaultInstanceForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.getDefaultInstance(); - } - - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter build() { - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter buildPartial() { - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter result = new org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.stringParamter_ = stringParamter_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.integerParameter_ = integerParameter_; - if (((from_bitField0_ & 0x00000004) == 0x00000004)) { - to_bitField0_ |= 0x00000004; - } - result.doubleParameter_ = doubleParameter_; - if (((from_bitField0_ & 0x00000008) == 0x00000008)) { - to_bitField0_ |= 0x00000008; - } - result.blobParameter_ = blobParameter_; - if (((from_bitField0_ & 0x00000010) == 0x00000010)) { - to_bitField0_ |= 0x00000010; - } - result.nullparameter_ = nullparameter_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter) { - return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter other) { - if (other == org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.getDefaultInstance()) return this; - if (other.hasStringParamter()) { - bitField0_ |= 0x00000001; - stringParamter_ = other.stringParamter_; - onChanged(); - } - if (other.hasIntegerParameter()) { - setIntegerParameter(other.getIntegerParameter()); - } - if (other.hasDoubleParameter()) { - setDoubleParameter(other.getDoubleParameter()); - } - if (other.hasBlobParameter()) { - setBlobParameter(other.getBlobParameter()); - } - if (other.hasNullparameter()) { - setNullparameter(other.getNullparameter()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - // optional string stringParamter = 1; - private java.lang.Object stringParamter_ = ""; - /** - * optional string stringParamter = 1; - */ - public boolean hasStringParamter() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional string stringParamter = 1; - */ - public java.lang.String getStringParamter() { - java.lang.Object ref = stringParamter_; - if (!(ref instanceof java.lang.String)) { - java.lang.String s = ((com.google.protobuf.ByteString) ref) - .toStringUtf8(); - stringParamter_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * optional string stringParamter = 1; - */ - public com.google.protobuf.ByteString - getStringParamterBytes() { - java.lang.Object ref = stringParamter_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - stringParamter_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * optional string stringParamter = 1; - */ - public Builder setStringParamter( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - stringParamter_ = value; - onChanged(); - return this; - } - /** - * optional string stringParamter = 1; - */ - public Builder clearStringParamter() { - bitField0_ = (bitField0_ & ~0x00000001); - stringParamter_ = getDefaultInstance().getStringParamter(); - onChanged(); - return this; - } - /** - * optional string stringParamter = 1; - */ - public Builder setStringParamterBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - stringParamter_ = value; - onChanged(); - return this; - } - - // optional uint64 integerParameter = 2; - private long integerParameter_ ; - /** - * optional uint64 integerParameter = 2; - */ - public boolean hasIntegerParameter() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional uint64 integerParameter = 2; - */ - public long getIntegerParameter() { - return integerParameter_; - } - /** - * optional uint64 integerParameter = 2; - */ - public Builder setIntegerParameter(long value) { - bitField0_ |= 0x00000002; - integerParameter_ = value; - onChanged(); - return this; - } - /** - * optional uint64 integerParameter = 2; - */ - public Builder clearIntegerParameter() { - bitField0_ = (bitField0_ & ~0x00000002); - integerParameter_ = 0L; - onChanged(); - return this; - } - - // optional double doubleParameter = 3; - private double doubleParameter_ ; - /** - * optional double doubleParameter = 3; - */ - public boolean hasDoubleParameter() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - /** - * optional double doubleParameter = 3; - */ - public double getDoubleParameter() { - return doubleParameter_; - } - /** - * optional double doubleParameter = 3; - */ - public Builder setDoubleParameter(double value) { - bitField0_ |= 0x00000004; - doubleParameter_ = value; - onChanged(); - return this; - } - /** - * optional double doubleParameter = 3; - */ - public Builder clearDoubleParameter() { - bitField0_ = (bitField0_ & ~0x00000004); - doubleParameter_ = 0D; - onChanged(); - return this; - } - - // optional bytes blobParameter = 4; - private com.google.protobuf.ByteString blobParameter_ = com.google.protobuf.ByteString.EMPTY; - /** - * optional bytes blobParameter = 4; - */ - public boolean hasBlobParameter() { - return ((bitField0_ & 0x00000008) == 0x00000008); - } - /** - * optional bytes blobParameter = 4; - */ - public com.google.protobuf.ByteString getBlobParameter() { - return blobParameter_; - } - /** - * optional bytes blobParameter = 4; - */ - public Builder setBlobParameter(com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000008; - blobParameter_ = value; - onChanged(); - return this; - } - /** - * optional bytes blobParameter = 4; - */ - public Builder clearBlobParameter() { - bitField0_ = (bitField0_ & ~0x00000008); - blobParameter_ = getDefaultInstance().getBlobParameter(); - onChanged(); - return this; - } - - // optional bool nullparameter = 5; - private boolean nullparameter_ ; - /** - * optional bool nullparameter = 5; - */ - public boolean hasNullparameter() { - return ((bitField0_ & 0x00000010) == 0x00000010); - } - /** - * optional bool nullparameter = 5; - */ - public boolean getNullparameter() { - return nullparameter_; - } - /** - * optional bool nullparameter = 5; - */ - public Builder setNullparameter(boolean value) { - bitField0_ |= 0x00000010; - nullparameter_ = value; - onChanged(); - return this; - } - /** - * optional bool nullparameter = 5; - */ - public Builder clearNullparameter() { - bitField0_ = (bitField0_ & ~0x00000010); - nullparameter_ = false; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:signal.SqlStatement.SqlParameter) - } - - static { - defaultInstance = new SqlParameter(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:signal.SqlStatement.SqlParameter) - } - - private int bitField0_; - // optional string statement = 1; - public static final int STATEMENT_FIELD_NUMBER = 1; - private java.lang.Object statement_; - /** - * optional string statement = 1; - */ - public boolean hasStatement() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional string statement = 1; - */ - public java.lang.String getStatement() { - java.lang.Object ref = statement_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - statement_ = s; - } - return s; - } - } - /** - * optional string statement = 1; - */ - public com.google.protobuf.ByteString - getStatementBytes() { - java.lang.Object ref = statement_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - statement_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // repeated .signal.SqlStatement.SqlParameter parameters = 2; - public static final int PARAMETERS_FIELD_NUMBER = 2; - private java.util.List parameters_; - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public java.util.List getParametersList() { - return parameters_; - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public java.util.List - getParametersOrBuilderList() { - return parameters_; - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public int getParametersCount() { - return parameters_.size(); - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter getParameters(int index) { - return parameters_.get(index); - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder getParametersOrBuilder( - int index) { - return parameters_.get(index); - } - - private void initFields() { - statement_ = ""; - parameters_ = java.util.Collections.emptyList(); - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getStatementBytes()); - } - for (int i = 0; i < parameters_.size(); i++) { - output.writeMessage(2, parameters_.get(i)); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getStatementBytes()); - } - for (int i = 0; i < parameters_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, parameters_.get(i)); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code signal.SqlStatement} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.class, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder.class); - } - - // Construct using org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - getParametersFieldBuilder(); - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - statement_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - if (parametersBuilder_ == null) { - parameters_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); - } else { - parametersBuilder_.clear(); - } - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SqlStatement_descriptor; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement getDefaultInstanceForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance(); - } - - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement build() { - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement buildPartial() { - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement result = new org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.statement_ = statement_; - if (parametersBuilder_ == null) { - if (((bitField0_ & 0x00000002) == 0x00000002)) { - parameters_ = java.util.Collections.unmodifiableList(parameters_); - bitField0_ = (bitField0_ & ~0x00000002); - } - result.parameters_ = parameters_; - } else { - result.parameters_ = parametersBuilder_.build(); - } - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement) { - return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement other) { - if (other == org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance()) return this; - if (other.hasStatement()) { - bitField0_ |= 0x00000001; - statement_ = other.statement_; - onChanged(); - } - if (parametersBuilder_ == null) { - if (!other.parameters_.isEmpty()) { - if (parameters_.isEmpty()) { - parameters_ = other.parameters_; - bitField0_ = (bitField0_ & ~0x00000002); - } else { - ensureParametersIsMutable(); - parameters_.addAll(other.parameters_); - } - onChanged(); - } - } else { - if (!other.parameters_.isEmpty()) { - if (parametersBuilder_.isEmpty()) { - parametersBuilder_.dispose(); - parametersBuilder_ = null; - parameters_ = other.parameters_; - bitField0_ = (bitField0_ & ~0x00000002); - parametersBuilder_ = - com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? - getParametersFieldBuilder() : null; - } else { - parametersBuilder_.addAllMessages(other.parameters_); - } - } - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - // optional string statement = 1; - private java.lang.Object statement_ = ""; - /** - * optional string statement = 1; - */ - public boolean hasStatement() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional string statement = 1; - */ - public java.lang.String getStatement() { - java.lang.Object ref = statement_; - if (!(ref instanceof java.lang.String)) { - java.lang.String s = ((com.google.protobuf.ByteString) ref) - .toStringUtf8(); - statement_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * optional string statement = 1; - */ - public com.google.protobuf.ByteString - getStatementBytes() { - java.lang.Object ref = statement_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - statement_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * optional string statement = 1; - */ - public Builder setStatement( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - statement_ = value; - onChanged(); - return this; - } - /** - * optional string statement = 1; - */ - public Builder clearStatement() { - bitField0_ = (bitField0_ & ~0x00000001); - statement_ = getDefaultInstance().getStatement(); - onChanged(); - return this; - } - /** - * optional string statement = 1; - */ - public Builder setStatementBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - statement_ = value; - onChanged(); - return this; - } - - // repeated .signal.SqlStatement.SqlParameter parameters = 2; - private java.util.List parameters_ = - java.util.Collections.emptyList(); - private void ensureParametersIsMutable() { - if (!((bitField0_ & 0x00000002) == 0x00000002)) { - parameters_ = new java.util.ArrayList(parameters_); - bitField0_ |= 0x00000002; - } - } - - private com.google.protobuf.RepeatedFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder> parametersBuilder_; - - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public java.util.List getParametersList() { - if (parametersBuilder_ == null) { - return java.util.Collections.unmodifiableList(parameters_); - } else { - return parametersBuilder_.getMessageList(); - } - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public int getParametersCount() { - if (parametersBuilder_ == null) { - return parameters_.size(); - } else { - return parametersBuilder_.getCount(); - } - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter getParameters(int index) { - if (parametersBuilder_ == null) { - return parameters_.get(index); - } else { - return parametersBuilder_.getMessage(index); - } - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public Builder setParameters( - int index, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter value) { - if (parametersBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureParametersIsMutable(); - parameters_.set(index, value); - onChanged(); - } else { - parametersBuilder_.setMessage(index, value); - } - return this; - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public Builder setParameters( - int index, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder builderForValue) { - if (parametersBuilder_ == null) { - ensureParametersIsMutable(); - parameters_.set(index, builderForValue.build()); - onChanged(); - } else { - parametersBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public Builder addParameters(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter value) { - if (parametersBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureParametersIsMutable(); - parameters_.add(value); - onChanged(); - } else { - parametersBuilder_.addMessage(value); - } - return this; - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public Builder addParameters( - int index, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter value) { - if (parametersBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureParametersIsMutable(); - parameters_.add(index, value); - onChanged(); - } else { - parametersBuilder_.addMessage(index, value); - } - return this; - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public Builder addParameters( - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder builderForValue) { - if (parametersBuilder_ == null) { - ensureParametersIsMutable(); - parameters_.add(builderForValue.build()); - onChanged(); - } else { - parametersBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public Builder addParameters( - int index, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder builderForValue) { - if (parametersBuilder_ == null) { - ensureParametersIsMutable(); - parameters_.add(index, builderForValue.build()); - onChanged(); - } else { - parametersBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public Builder addAllParameters( - java.lang.Iterable values) { - if (parametersBuilder_ == null) { - ensureParametersIsMutable(); - super.addAll(values, parameters_); - onChanged(); - } else { - parametersBuilder_.addAllMessages(values); - } - return this; - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public Builder clearParameters() { - if (parametersBuilder_ == null) { - parameters_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - } else { - parametersBuilder_.clear(); - } - return this; - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public Builder removeParameters(int index) { - if (parametersBuilder_ == null) { - ensureParametersIsMutable(); - parameters_.remove(index); - onChanged(); - } else { - parametersBuilder_.remove(index); - } - return this; - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder getParametersBuilder( - int index) { - return getParametersFieldBuilder().getBuilder(index); - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder getParametersOrBuilder( - int index) { - if (parametersBuilder_ == null) { - return parameters_.get(index); } else { - return parametersBuilder_.getMessageOrBuilder(index); - } - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public java.util.List - getParametersOrBuilderList() { - if (parametersBuilder_ != null) { - return parametersBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(parameters_); - } - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder addParametersBuilder() { - return getParametersFieldBuilder().addBuilder( - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.getDefaultInstance()); - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder addParametersBuilder( - int index) { - return getParametersFieldBuilder().addBuilder( - index, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.getDefaultInstance()); - } - /** - * repeated .signal.SqlStatement.SqlParameter parameters = 2; - */ - public java.util.List - getParametersBuilderList() { - return getParametersFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder> - getParametersFieldBuilder() { - if (parametersBuilder_ == null) { - parametersBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameter.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.SqlParameterOrBuilder>( - parameters_, - ((bitField0_ & 0x00000002) == 0x00000002), - getParentForChildren(), - isClean()); - parameters_ = null; - } - return parametersBuilder_; - } - - // @@protoc_insertion_point(builder_scope:signal.SqlStatement) - } - - static { - defaultInstance = new SqlStatement(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:signal.SqlStatement) - } - - public interface SharedPreferenceOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // optional string file = 1; - /** - * optional string file = 1; - */ - boolean hasFile(); - /** - * optional string file = 1; - */ - java.lang.String getFile(); - /** - * optional string file = 1; - */ - com.google.protobuf.ByteString - getFileBytes(); - - // optional string key = 2; - /** - * optional string key = 2; - */ - boolean hasKey(); - /** - * optional string key = 2; - */ - java.lang.String getKey(); - /** - * optional string key = 2; - */ - com.google.protobuf.ByteString - getKeyBytes(); - - // optional string value = 3; - /** - * optional string value = 3; - */ - boolean hasValue(); - /** - * optional string value = 3; - */ - java.lang.String getValue(); - /** - * optional string value = 3; - */ - com.google.protobuf.ByteString - getValueBytes(); - } - /** - * Protobuf type {@code signal.SharedPreference} - */ - public static final class SharedPreference extends - com.google.protobuf.GeneratedMessage - implements SharedPreferenceOrBuilder { - // Use SharedPreference.newBuilder() to construct. - private SharedPreference(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - this.unknownFields = builder.getUnknownFields(); - } - private SharedPreference(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } - - private static final SharedPreference defaultInstance; - public static SharedPreference getDefaultInstance() { - return defaultInstance; - } - - public SharedPreference getDefaultInstanceForType() { - return defaultInstance; - } - - private final com.google.protobuf.UnknownFieldSet unknownFields; - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private SharedPreference( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - initFields(); - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - done = true; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - file_ = input.readBytes(); - break; - } - case 18: { - bitField0_ |= 0x00000002; - key_ = input.readBytes(); - break; - } - case 26: { - bitField0_ |= 0x00000004; - value_ = input.readBytes(); - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e.getMessage()).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.class, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder.class); - } - - public static com.google.protobuf.Parser PARSER = - new com.google.protobuf.AbstractParser() { - public SharedPreference parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new SharedPreference(input, extensionRegistry); - } - }; - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - private int bitField0_; - // optional string file = 1; - public static final int FILE_FIELD_NUMBER = 1; - private java.lang.Object file_; - /** - * optional string file = 1; - */ - public boolean hasFile() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional string file = 1; - */ - public java.lang.String getFile() { - java.lang.Object ref = file_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - file_ = s; - } - return s; - } - } - /** - * optional string file = 1; - */ - public com.google.protobuf.ByteString - getFileBytes() { - java.lang.Object ref = file_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - file_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // optional string key = 2; - public static final int KEY_FIELD_NUMBER = 2; - private java.lang.Object key_; - /** - * optional string key = 2; - */ - public boolean hasKey() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional string key = 2; - */ - public java.lang.String getKey() { - java.lang.Object ref = key_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - key_ = s; - } - return s; - } - } - /** - * optional string key = 2; - */ - public com.google.protobuf.ByteString - getKeyBytes() { - java.lang.Object ref = key_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - key_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // optional string value = 3; - public static final int VALUE_FIELD_NUMBER = 3; - private java.lang.Object value_; - /** - * optional string value = 3; - */ - public boolean hasValue() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - /** - * optional string value = 3; - */ - public java.lang.String getValue() { - java.lang.Object ref = value_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - value_ = s; - } - return s; - } - } - /** - * optional string value = 3; - */ - public com.google.protobuf.ByteString - getValueBytes() { - java.lang.Object ref = value_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - value_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private void initFields() { - file_ = ""; - key_ = ""; - value_ = ""; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getFileBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeBytes(2, getKeyBytes()); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeBytes(3, getValueBytes()); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getFileBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(2, getKeyBytes()); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(3, getValueBytes()); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code signal.SharedPreference} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.class, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder.class); - } - - // Construct using org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - file_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - key_ = ""; - bitField0_ = (bitField0_ & ~0x00000002); - value_ = ""; - bitField0_ = (bitField0_ & ~0x00000004); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_SharedPreference_descriptor; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference getDefaultInstanceForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance(); - } - - public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference build() { - org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference buildPartial() { - org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference result = new org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.file_ = file_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.key_ = key_; - if (((from_bitField0_ & 0x00000004) == 0x00000004)) { - to_bitField0_ |= 0x00000004; - } - result.value_ = value_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference) { - return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference other) { - if (other == org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance()) return this; - if (other.hasFile()) { - bitField0_ |= 0x00000001; - file_ = other.file_; - onChanged(); - } - if (other.hasKey()) { - bitField0_ |= 0x00000002; - key_ = other.key_; - onChanged(); - } - if (other.hasValue()) { - bitField0_ |= 0x00000004; - value_ = other.value_; - onChanged(); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - // optional string file = 1; - private java.lang.Object file_ = ""; - /** - * optional string file = 1; - */ - public boolean hasFile() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional string file = 1; - */ - public java.lang.String getFile() { - java.lang.Object ref = file_; - if (!(ref instanceof java.lang.String)) { - java.lang.String s = ((com.google.protobuf.ByteString) ref) - .toStringUtf8(); - file_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * optional string file = 1; - */ - public com.google.protobuf.ByteString - getFileBytes() { - java.lang.Object ref = file_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - file_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * optional string file = 1; - */ - public Builder setFile( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - file_ = value; - onChanged(); - return this; - } - /** - * optional string file = 1; - */ - public Builder clearFile() { - bitField0_ = (bitField0_ & ~0x00000001); - file_ = getDefaultInstance().getFile(); - onChanged(); - return this; - } - /** - * optional string file = 1; - */ - public Builder setFileBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - file_ = value; - onChanged(); - return this; - } - - // optional string key = 2; - private java.lang.Object key_ = ""; - /** - * optional string key = 2; - */ - public boolean hasKey() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional string key = 2; - */ - public java.lang.String getKey() { - java.lang.Object ref = key_; - if (!(ref instanceof java.lang.String)) { - java.lang.String s = ((com.google.protobuf.ByteString) ref) - .toStringUtf8(); - key_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * optional string key = 2; - */ - public com.google.protobuf.ByteString - getKeyBytes() { - java.lang.Object ref = key_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - key_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * optional string key = 2; - */ - public Builder setKey( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; - key_ = value; - onChanged(); - return this; - } - /** - * optional string key = 2; - */ - public Builder clearKey() { - bitField0_ = (bitField0_ & ~0x00000002); - key_ = getDefaultInstance().getKey(); - onChanged(); - return this; - } - /** - * optional string key = 2; - */ - public Builder setKeyBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; - key_ = value; - onChanged(); - return this; - } - - // optional string value = 3; - private java.lang.Object value_ = ""; - /** - * optional string value = 3; - */ - public boolean hasValue() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - /** - * optional string value = 3; - */ - public java.lang.String getValue() { - java.lang.Object ref = value_; - if (!(ref instanceof java.lang.String)) { - java.lang.String s = ((com.google.protobuf.ByteString) ref) - .toStringUtf8(); - value_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * optional string value = 3; - */ - public com.google.protobuf.ByteString - getValueBytes() { - java.lang.Object ref = value_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - value_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * optional string value = 3; - */ - public Builder setValue( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; - value_ = value; - onChanged(); - return this; - } - /** - * optional string value = 3; - */ - public Builder clearValue() { - bitField0_ = (bitField0_ & ~0x00000004); - value_ = getDefaultInstance().getValue(); - onChanged(); - return this; - } - /** - * optional string value = 3; - */ - public Builder setValueBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; - value_ = value; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:signal.SharedPreference) - } - - static { - defaultInstance = new SharedPreference(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:signal.SharedPreference) - } - - public interface AttachmentOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // optional uint64 rowId = 1; - /** - * optional uint64 rowId = 1; - */ - boolean hasRowId(); - /** - * optional uint64 rowId = 1; - */ - long getRowId(); - - // optional uint64 attachmentId = 2; - /** - * optional uint64 attachmentId = 2; - */ - boolean hasAttachmentId(); - /** - * optional uint64 attachmentId = 2; - */ - long getAttachmentId(); - - // optional uint32 length = 3; - /** - * optional uint32 length = 3; - */ - boolean hasLength(); - /** - * optional uint32 length = 3; - */ - int getLength(); - } - /** - * Protobuf type {@code signal.Attachment} - */ - public static final class Attachment extends - com.google.protobuf.GeneratedMessage - implements AttachmentOrBuilder { - // Use Attachment.newBuilder() to construct. - private Attachment(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - this.unknownFields = builder.getUnknownFields(); - } - private Attachment(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } - - private static final Attachment defaultInstance; - public static Attachment getDefaultInstance() { - return defaultInstance; - } - - public Attachment getDefaultInstanceForType() { - return defaultInstance; - } - - private final com.google.protobuf.UnknownFieldSet unknownFields; - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private Attachment( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - initFields(); - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - done = true; - } - break; - } - case 8: { - bitField0_ |= 0x00000001; - rowId_ = input.readUInt64(); - break; - } - case 16: { - bitField0_ |= 0x00000002; - attachmentId_ = input.readUInt64(); - break; - } - case 24: { - bitField0_ |= 0x00000004; - length_ = input.readUInt32(); - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e.getMessage()).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.Attachment.class, org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder.class); - } - - public static com.google.protobuf.Parser PARSER = - new com.google.protobuf.AbstractParser() { - public Attachment parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new Attachment(input, extensionRegistry); - } - }; - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - private int bitField0_; - // optional uint64 rowId = 1; - public static final int ROWID_FIELD_NUMBER = 1; - private long rowId_; - /** - * optional uint64 rowId = 1; - */ - public boolean hasRowId() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional uint64 rowId = 1; - */ - public long getRowId() { - return rowId_; - } - - // optional uint64 attachmentId = 2; - public static final int ATTACHMENTID_FIELD_NUMBER = 2; - private long attachmentId_; - /** - * optional uint64 attachmentId = 2; - */ - public boolean hasAttachmentId() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional uint64 attachmentId = 2; - */ - public long getAttachmentId() { - return attachmentId_; - } - - // optional uint32 length = 3; - public static final int LENGTH_FIELD_NUMBER = 3; - private int length_; - /** - * optional uint32 length = 3; - */ - public boolean hasLength() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - /** - * optional uint32 length = 3; - */ - public int getLength() { - return length_; - } - - private void initFields() { - rowId_ = 0L; - attachmentId_ = 0L; - length_ = 0; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeUInt64(1, rowId_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeUInt64(2, attachmentId_); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeUInt32(3, length_); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeUInt64Size(1, rowId_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeUInt64Size(2, attachmentId_); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - size += com.google.protobuf.CodedOutputStream - .computeUInt32Size(3, length_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Attachment parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.Attachment prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code signal.Attachment} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.Attachment.class, org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder.class); - } - - // Construct using org.thoughtcrime.securesms.backup.BackupProtos.Attachment.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - rowId_ = 0L; - bitField0_ = (bitField0_ & ~0x00000001); - attachmentId_ = 0L; - bitField0_ = (bitField0_ & ~0x00000002); - length_ = 0; - bitField0_ = (bitField0_ & ~0x00000004); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Attachment_descriptor; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.Attachment getDefaultInstanceForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance(); - } - - public org.thoughtcrime.securesms.backup.BackupProtos.Attachment build() { - org.thoughtcrime.securesms.backup.BackupProtos.Attachment result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.Attachment buildPartial() { - org.thoughtcrime.securesms.backup.BackupProtos.Attachment result = new org.thoughtcrime.securesms.backup.BackupProtos.Attachment(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.rowId_ = rowId_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.attachmentId_ = attachmentId_; - if (((from_bitField0_ & 0x00000004) == 0x00000004)) { - to_bitField0_ |= 0x00000004; - } - result.length_ = length_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.Attachment) { - return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.Attachment)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.Attachment other) { - if (other == org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance()) return this; - if (other.hasRowId()) { - setRowId(other.getRowId()); - } - if (other.hasAttachmentId()) { - setAttachmentId(other.getAttachmentId()); - } - if (other.hasLength()) { - setLength(other.getLength()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - org.thoughtcrime.securesms.backup.BackupProtos.Attachment parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.Attachment) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - // optional uint64 rowId = 1; - private long rowId_ ; - /** - * optional uint64 rowId = 1; - */ - public boolean hasRowId() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional uint64 rowId = 1; - */ - public long getRowId() { - return rowId_; - } - /** - * optional uint64 rowId = 1; - */ - public Builder setRowId(long value) { - bitField0_ |= 0x00000001; - rowId_ = value; - onChanged(); - return this; - } - /** - * optional uint64 rowId = 1; - */ - public Builder clearRowId() { - bitField0_ = (bitField0_ & ~0x00000001); - rowId_ = 0L; - onChanged(); - return this; - } - - // optional uint64 attachmentId = 2; - private long attachmentId_ ; - /** - * optional uint64 attachmentId = 2; - */ - public boolean hasAttachmentId() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional uint64 attachmentId = 2; - */ - public long getAttachmentId() { - return attachmentId_; - } - /** - * optional uint64 attachmentId = 2; - */ - public Builder setAttachmentId(long value) { - bitField0_ |= 0x00000002; - attachmentId_ = value; - onChanged(); - return this; - } - /** - * optional uint64 attachmentId = 2; - */ - public Builder clearAttachmentId() { - bitField0_ = (bitField0_ & ~0x00000002); - attachmentId_ = 0L; - onChanged(); - return this; - } - - // optional uint32 length = 3; - private int length_ ; - /** - * optional uint32 length = 3; - */ - public boolean hasLength() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - /** - * optional uint32 length = 3; - */ - public int getLength() { - return length_; - } - /** - * optional uint32 length = 3; - */ - public Builder setLength(int value) { - bitField0_ |= 0x00000004; - length_ = value; - onChanged(); - return this; - } - /** - * optional uint32 length = 3; - */ - public Builder clearLength() { - bitField0_ = (bitField0_ & ~0x00000004); - length_ = 0; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:signal.Attachment) - } - - static { - defaultInstance = new Attachment(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:signal.Attachment) - } - - public interface StickerOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // optional uint64 rowId = 1; - /** - * optional uint64 rowId = 1; - */ - boolean hasRowId(); - /** - * optional uint64 rowId = 1; - */ - long getRowId(); - - // optional uint32 length = 2; - /** - * optional uint32 length = 2; - */ - boolean hasLength(); - /** - * optional uint32 length = 2; - */ - int getLength(); - } - /** - * Protobuf type {@code signal.Sticker} - */ - public static final class Sticker extends - com.google.protobuf.GeneratedMessage - implements StickerOrBuilder { - // Use Sticker.newBuilder() to construct. - private Sticker(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - this.unknownFields = builder.getUnknownFields(); - } - private Sticker(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } - - private static final Sticker defaultInstance; - public static Sticker getDefaultInstance() { - return defaultInstance; - } - - public Sticker getDefaultInstanceForType() { - return defaultInstance; - } - - private final com.google.protobuf.UnknownFieldSet unknownFields; - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private Sticker( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - initFields(); - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - done = true; - } - break; - } - case 8: { - bitField0_ |= 0x00000001; - rowId_ = input.readUInt64(); - break; - } - case 16: { - bitField0_ |= 0x00000002; - length_ = input.readUInt32(); - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e.getMessage()).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Sticker_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Sticker_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.Sticker.class, org.thoughtcrime.securesms.backup.BackupProtos.Sticker.Builder.class); - } - - public static com.google.protobuf.Parser PARSER = - new com.google.protobuf.AbstractParser() { - public Sticker parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new Sticker(input, extensionRegistry); - } - }; - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - private int bitField0_; - // optional uint64 rowId = 1; - public static final int ROWID_FIELD_NUMBER = 1; - private long rowId_; - /** - * optional uint64 rowId = 1; - */ - public boolean hasRowId() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional uint64 rowId = 1; - */ - public long getRowId() { - return rowId_; - } - - // optional uint32 length = 2; - public static final int LENGTH_FIELD_NUMBER = 2; - private int length_; - /** - * optional uint32 length = 2; - */ - public boolean hasLength() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional uint32 length = 2; - */ - public int getLength() { - return length_; - } - - private void initFields() { - rowId_ = 0L; - length_ = 0; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeUInt64(1, rowId_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeUInt32(2, length_); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeUInt64Size(1, rowId_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeUInt32Size(2, length_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Sticker parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.Sticker prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code signal.Sticker} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements org.thoughtcrime.securesms.backup.BackupProtos.StickerOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Sticker_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Sticker_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.Sticker.class, org.thoughtcrime.securesms.backup.BackupProtos.Sticker.Builder.class); - } - - // Construct using org.thoughtcrime.securesms.backup.BackupProtos.Sticker.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - rowId_ = 0L; - bitField0_ = (bitField0_ & ~0x00000001); - length_ = 0; - bitField0_ = (bitField0_ & ~0x00000002); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Sticker_descriptor; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.Sticker getDefaultInstanceForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.Sticker.getDefaultInstance(); - } - - public org.thoughtcrime.securesms.backup.BackupProtos.Sticker build() { - org.thoughtcrime.securesms.backup.BackupProtos.Sticker result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.Sticker buildPartial() { - org.thoughtcrime.securesms.backup.BackupProtos.Sticker result = new org.thoughtcrime.securesms.backup.BackupProtos.Sticker(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.rowId_ = rowId_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.length_ = length_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.Sticker) { - return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.Sticker)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.Sticker other) { - if (other == org.thoughtcrime.securesms.backup.BackupProtos.Sticker.getDefaultInstance()) return this; - if (other.hasRowId()) { - setRowId(other.getRowId()); - } - if (other.hasLength()) { - setLength(other.getLength()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - org.thoughtcrime.securesms.backup.BackupProtos.Sticker parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.Sticker) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - // optional uint64 rowId = 1; - private long rowId_ ; - /** - * optional uint64 rowId = 1; - */ - public boolean hasRowId() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional uint64 rowId = 1; - */ - public long getRowId() { - return rowId_; - } - /** - * optional uint64 rowId = 1; - */ - public Builder setRowId(long value) { - bitField0_ |= 0x00000001; - rowId_ = value; - onChanged(); - return this; - } - /** - * optional uint64 rowId = 1; - */ - public Builder clearRowId() { - bitField0_ = (bitField0_ & ~0x00000001); - rowId_ = 0L; - onChanged(); - return this; - } - - // optional uint32 length = 2; - private int length_ ; - /** - * optional uint32 length = 2; - */ - public boolean hasLength() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional uint32 length = 2; - */ - public int getLength() { - return length_; - } - /** - * optional uint32 length = 2; - */ - public Builder setLength(int value) { - bitField0_ |= 0x00000002; - length_ = value; - onChanged(); - return this; - } - /** - * optional uint32 length = 2; - */ - public Builder clearLength() { - bitField0_ = (bitField0_ & ~0x00000002); - length_ = 0; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:signal.Sticker) - } - - static { - defaultInstance = new Sticker(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:signal.Sticker) - } - - public interface AvatarOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // optional string name = 1; - /** - * optional string name = 1; - */ - boolean hasName(); - /** - * optional string name = 1; - */ - java.lang.String getName(); - /** - * optional string name = 1; - */ - com.google.protobuf.ByteString - getNameBytes(); - - // optional uint32 length = 2; - /** - * optional uint32 length = 2; - */ - boolean hasLength(); - /** - * optional uint32 length = 2; - */ - int getLength(); - } - /** - * Protobuf type {@code signal.Avatar} - */ - public static final class Avatar extends - com.google.protobuf.GeneratedMessage - implements AvatarOrBuilder { - // Use Avatar.newBuilder() to construct. - private Avatar(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - this.unknownFields = builder.getUnknownFields(); - } - private Avatar(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } - - private static final Avatar defaultInstance; - public static Avatar getDefaultInstance() { - return defaultInstance; - } - - public Avatar getDefaultInstanceForType() { - return defaultInstance; - } - - private final com.google.protobuf.UnknownFieldSet unknownFields; - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private Avatar( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - initFields(); - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - done = true; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - name_ = input.readBytes(); - break; - } - case 16: { - bitField0_ |= 0x00000002; - length_ = input.readUInt32(); - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e.getMessage()).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Avatar_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Avatar_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.Avatar.class, org.thoughtcrime.securesms.backup.BackupProtos.Avatar.Builder.class); - } - - public static com.google.protobuf.Parser PARSER = - new com.google.protobuf.AbstractParser() { - public Avatar parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new Avatar(input, extensionRegistry); - } - }; - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - private int bitField0_; - // optional string name = 1; - public static final int NAME_FIELD_NUMBER = 1; - private java.lang.Object name_; - /** - * optional string name = 1; - */ - public boolean hasName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional string name = 1; - */ - public java.lang.String getName() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - name_ = s; - } - return s; - } - } - /** - * optional string name = 1; - */ - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - // optional uint32 length = 2; - public static final int LENGTH_FIELD_NUMBER = 2; - private int length_; - /** - * optional uint32 length = 2; - */ - public boolean hasLength() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional uint32 length = 2; - */ - public int getLength() { - return length_; - } - - private void initFields() { - name_ = ""; - length_ = 0; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, getNameBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeUInt32(2, length_); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, getNameBytes()); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeUInt32Size(2, length_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Avatar parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.Avatar prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code signal.Avatar} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements org.thoughtcrime.securesms.backup.BackupProtos.AvatarOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Avatar_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Avatar_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.Avatar.class, org.thoughtcrime.securesms.backup.BackupProtos.Avatar.Builder.class); - } - - // Construct using org.thoughtcrime.securesms.backup.BackupProtos.Avatar.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - name_ = ""; - bitField0_ = (bitField0_ & ~0x00000001); - length_ = 0; - bitField0_ = (bitField0_ & ~0x00000002); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Avatar_descriptor; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.Avatar getDefaultInstanceForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.Avatar.getDefaultInstance(); - } - - public org.thoughtcrime.securesms.backup.BackupProtos.Avatar build() { - org.thoughtcrime.securesms.backup.BackupProtos.Avatar result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.Avatar buildPartial() { - org.thoughtcrime.securesms.backup.BackupProtos.Avatar result = new org.thoughtcrime.securesms.backup.BackupProtos.Avatar(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.name_ = name_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.length_ = length_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.Avatar) { - return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.Avatar)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.Avatar other) { - if (other == org.thoughtcrime.securesms.backup.BackupProtos.Avatar.getDefaultInstance()) return this; - if (other.hasName()) { - bitField0_ |= 0x00000001; - name_ = other.name_; - onChanged(); - } - if (other.hasLength()) { - setLength(other.getLength()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - org.thoughtcrime.securesms.backup.BackupProtos.Avatar parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.Avatar) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - // optional string name = 1; - private java.lang.Object name_ = ""; - /** - * optional string name = 1; - */ - public boolean hasName() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional string name = 1; - */ - public java.lang.String getName() { - java.lang.Object ref = name_; - if (!(ref instanceof java.lang.String)) { - java.lang.String s = ((com.google.protobuf.ByteString) ref) - .toStringUtf8(); - name_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * optional string name = 1; - */ - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * optional string name = 1; - */ - public Builder setName( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - name_ = value; - onChanged(); - return this; - } - /** - * optional string name = 1; - */ - public Builder clearName() { - bitField0_ = (bitField0_ & ~0x00000001); - name_ = getDefaultInstance().getName(); - onChanged(); - return this; - } - /** - * optional string name = 1; - */ - public Builder setNameBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - name_ = value; - onChanged(); - return this; - } - - // optional uint32 length = 2; - private int length_ ; - /** - * optional uint32 length = 2; - */ - public boolean hasLength() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional uint32 length = 2; - */ - public int getLength() { - return length_; - } - /** - * optional uint32 length = 2; - */ - public Builder setLength(int value) { - bitField0_ |= 0x00000002; - length_ = value; - onChanged(); - return this; - } - /** - * optional uint32 length = 2; - */ - public Builder clearLength() { - bitField0_ = (bitField0_ & ~0x00000002); - length_ = 0; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:signal.Avatar) - } - - static { - defaultInstance = new Avatar(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:signal.Avatar) - } - - public interface DatabaseVersionOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // optional uint32 version = 1; - /** - * optional uint32 version = 1; - */ - boolean hasVersion(); - /** - * optional uint32 version = 1; - */ - int getVersion(); - } - /** - * Protobuf type {@code signal.DatabaseVersion} - */ - public static final class DatabaseVersion extends - com.google.protobuf.GeneratedMessage - implements DatabaseVersionOrBuilder { - // Use DatabaseVersion.newBuilder() to construct. - private DatabaseVersion(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - this.unknownFields = builder.getUnknownFields(); - } - private DatabaseVersion(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } - - private static final DatabaseVersion defaultInstance; - public static DatabaseVersion getDefaultInstance() { - return defaultInstance; - } - - public DatabaseVersion getDefaultInstanceForType() { - return defaultInstance; - } - - private final com.google.protobuf.UnknownFieldSet unknownFields; - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private DatabaseVersion( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - initFields(); - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - done = true; - } - break; - } - case 8: { - bitField0_ |= 0x00000001; - version_ = input.readUInt32(); - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e.getMessage()).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.class, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder.class); - } - - public static com.google.protobuf.Parser PARSER = - new com.google.protobuf.AbstractParser() { - public DatabaseVersion parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new DatabaseVersion(input, extensionRegistry); - } - }; - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - private int bitField0_; - // optional uint32 version = 1; - public static final int VERSION_FIELD_NUMBER = 1; - private int version_; - /** - * optional uint32 version = 1; - */ - public boolean hasVersion() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional uint32 version = 1; - */ - public int getVersion() { - return version_; - } - - private void initFields() { - version_ = 0; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeUInt32(1, version_); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeUInt32Size(1, version_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code signal.DatabaseVersion} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.class, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder.class); - } - - // Construct using org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - version_ = 0; - bitField0_ = (bitField0_ & ~0x00000001); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_DatabaseVersion_descriptor; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion getDefaultInstanceForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance(); - } - - public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion build() { - org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion buildPartial() { - org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion result = new org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.version_ = version_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion) { - return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion other) { - if (other == org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance()) return this; - if (other.hasVersion()) { - setVersion(other.getVersion()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - // optional uint32 version = 1; - private int version_ ; - /** - * optional uint32 version = 1; - */ - public boolean hasVersion() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional uint32 version = 1; - */ - public int getVersion() { - return version_; - } - /** - * optional uint32 version = 1; - */ - public Builder setVersion(int value) { - bitField0_ |= 0x00000001; - version_ = value; - onChanged(); - return this; - } - /** - * optional uint32 version = 1; - */ - public Builder clearVersion() { - bitField0_ = (bitField0_ & ~0x00000001); - version_ = 0; - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:signal.DatabaseVersion) - } - - static { - defaultInstance = new DatabaseVersion(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:signal.DatabaseVersion) - } - - public interface HeaderOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // optional bytes iv = 1; - /** - * optional bytes iv = 1; - */ - boolean hasIv(); - /** - * optional bytes iv = 1; - */ - com.google.protobuf.ByteString getIv(); - - // optional bytes salt = 2; - /** - * optional bytes salt = 2; - */ - boolean hasSalt(); - /** - * optional bytes salt = 2; - */ - com.google.protobuf.ByteString getSalt(); - } - /** - * Protobuf type {@code signal.Header} - */ - public static final class Header extends - com.google.protobuf.GeneratedMessage - implements HeaderOrBuilder { - // Use Header.newBuilder() to construct. - private Header(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - this.unknownFields = builder.getUnknownFields(); - } - private Header(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } - - private static final Header defaultInstance; - public static Header getDefaultInstance() { - return defaultInstance; - } - - public Header getDefaultInstanceForType() { - return defaultInstance; - } - - private final com.google.protobuf.UnknownFieldSet unknownFields; - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private Header( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - initFields(); - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - done = true; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - iv_ = input.readBytes(); - break; - } - case 18: { - bitField0_ |= 0x00000002; - salt_ = input.readBytes(); - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e.getMessage()).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Header_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Header_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.Header.class, org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder.class); - } - - public static com.google.protobuf.Parser
PARSER = - new com.google.protobuf.AbstractParser
() { - public Header parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new Header(input, extensionRegistry); - } - }; - - @java.lang.Override - public com.google.protobuf.Parser
getParserForType() { - return PARSER; - } - - private int bitField0_; - // optional bytes iv = 1; - public static final int IV_FIELD_NUMBER = 1; - private com.google.protobuf.ByteString iv_; - /** - * optional bytes iv = 1; - */ - public boolean hasIv() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional bytes iv = 1; - */ - public com.google.protobuf.ByteString getIv() { - return iv_; - } - - // optional bytes salt = 2; - public static final int SALT_FIELD_NUMBER = 2; - private com.google.protobuf.ByteString salt_; - /** - * optional bytes salt = 2; - */ - public boolean hasSalt() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional bytes salt = 2; - */ - public com.google.protobuf.ByteString getSalt() { - return salt_; - } - - private void initFields() { - iv_ = com.google.protobuf.ByteString.EMPTY; - salt_ = com.google.protobuf.ByteString.EMPTY; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, iv_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeBytes(2, salt_); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, iv_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(2, salt_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.Header parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.Header prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code signal.Header} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Header_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Header_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.Header.class, org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder.class); - } - - // Construct using org.thoughtcrime.securesms.backup.BackupProtos.Header.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - iv_ = com.google.protobuf.ByteString.EMPTY; - bitField0_ = (bitField0_ & ~0x00000001); - salt_ = com.google.protobuf.ByteString.EMPTY; - bitField0_ = (bitField0_ & ~0x00000002); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_Header_descriptor; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.Header getDefaultInstanceForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance(); - } - - public org.thoughtcrime.securesms.backup.BackupProtos.Header build() { - org.thoughtcrime.securesms.backup.BackupProtos.Header result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.Header buildPartial() { - org.thoughtcrime.securesms.backup.BackupProtos.Header result = new org.thoughtcrime.securesms.backup.BackupProtos.Header(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.iv_ = iv_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.salt_ = salt_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.Header) { - return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.Header)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.Header other) { - if (other == org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance()) return this; - if (other.hasIv()) { - setIv(other.getIv()); - } - if (other.hasSalt()) { - setSalt(other.getSalt()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - org.thoughtcrime.securesms.backup.BackupProtos.Header parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.Header) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - // optional bytes iv = 1; - private com.google.protobuf.ByteString iv_ = com.google.protobuf.ByteString.EMPTY; - /** - * optional bytes iv = 1; - */ - public boolean hasIv() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional bytes iv = 1; - */ - public com.google.protobuf.ByteString getIv() { - return iv_; - } - /** - * optional bytes iv = 1; - */ - public Builder setIv(com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - iv_ = value; - onChanged(); - return this; - } - /** - * optional bytes iv = 1; - */ - public Builder clearIv() { - bitField0_ = (bitField0_ & ~0x00000001); - iv_ = getDefaultInstance().getIv(); - onChanged(); - return this; - } - - // optional bytes salt = 2; - private com.google.protobuf.ByteString salt_ = com.google.protobuf.ByteString.EMPTY; - /** - * optional bytes salt = 2; - */ - public boolean hasSalt() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional bytes salt = 2; - */ - public com.google.protobuf.ByteString getSalt() { - return salt_; - } - /** - * optional bytes salt = 2; - */ - public Builder setSalt(com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; - salt_ = value; - onChanged(); - return this; - } - /** - * optional bytes salt = 2; - */ - public Builder clearSalt() { - bitField0_ = (bitField0_ & ~0x00000002); - salt_ = getDefaultInstance().getSalt(); - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:signal.Header) - } - - static { - defaultInstance = new Header(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:signal.Header) - } - - public interface BackupFrameOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // optional .signal.Header header = 1; - /** - * optional .signal.Header header = 1; - */ - boolean hasHeader(); - /** - * optional .signal.Header header = 1; - */ - org.thoughtcrime.securesms.backup.BackupProtos.Header getHeader(); - /** - * optional .signal.Header header = 1; - */ - org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder getHeaderOrBuilder(); - - // optional .signal.SqlStatement statement = 2; - /** - * optional .signal.SqlStatement statement = 2; - */ - boolean hasStatement(); - /** - * optional .signal.SqlStatement statement = 2; - */ - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement getStatement(); - /** - * optional .signal.SqlStatement statement = 2; - */ - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder getStatementOrBuilder(); - - // optional .signal.SharedPreference preference = 3; - /** - * optional .signal.SharedPreference preference = 3; - */ - boolean hasPreference(); - /** - * optional .signal.SharedPreference preference = 3; - */ - org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference getPreference(); - /** - * optional .signal.SharedPreference preference = 3; - */ - org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder getPreferenceOrBuilder(); - - // optional .signal.Attachment attachment = 4; - /** - * optional .signal.Attachment attachment = 4; - */ - boolean hasAttachment(); - /** - * optional .signal.Attachment attachment = 4; - */ - org.thoughtcrime.securesms.backup.BackupProtos.Attachment getAttachment(); - /** - * optional .signal.Attachment attachment = 4; - */ - org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder getAttachmentOrBuilder(); - - // optional .signal.DatabaseVersion version = 5; - /** - * optional .signal.DatabaseVersion version = 5; - */ - boolean hasVersion(); - /** - * optional .signal.DatabaseVersion version = 5; - */ - org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion getVersion(); - /** - * optional .signal.DatabaseVersion version = 5; - */ - org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder getVersionOrBuilder(); - - // optional bool end = 6; - /** - * optional bool end = 6; - */ - boolean hasEnd(); - /** - * optional bool end = 6; - */ - boolean getEnd(); - - // optional .signal.Avatar avatar = 7; - /** - * optional .signal.Avatar avatar = 7; - */ - boolean hasAvatar(); - /** - * optional .signal.Avatar avatar = 7; - */ - org.thoughtcrime.securesms.backup.BackupProtos.Avatar getAvatar(); - /** - * optional .signal.Avatar avatar = 7; - */ - org.thoughtcrime.securesms.backup.BackupProtos.AvatarOrBuilder getAvatarOrBuilder(); - - // optional .signal.Sticker sticker = 8; - /** - * optional .signal.Sticker sticker = 8; - */ - boolean hasSticker(); - /** - * optional .signal.Sticker sticker = 8; - */ - org.thoughtcrime.securesms.backup.BackupProtos.Sticker getSticker(); - /** - * optional .signal.Sticker sticker = 8; - */ - org.thoughtcrime.securesms.backup.BackupProtos.StickerOrBuilder getStickerOrBuilder(); - } - /** - * Protobuf type {@code signal.BackupFrame} - */ - public static final class BackupFrame extends - com.google.protobuf.GeneratedMessage - implements BackupFrameOrBuilder { - // Use BackupFrame.newBuilder() to construct. - private BackupFrame(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - this.unknownFields = builder.getUnknownFields(); - } - private BackupFrame(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } - - private static final BackupFrame defaultInstance; - public static BackupFrame getDefaultInstance() { - return defaultInstance; - } - - public BackupFrame getDefaultInstanceForType() { - return defaultInstance; - } - - private final com.google.protobuf.UnknownFieldSet unknownFields; - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private BackupFrame( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - initFields(); - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - done = true; - } - break; - } - case 10: { - org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder subBuilder = null; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - subBuilder = header_.toBuilder(); - } - header_ = input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.Header.PARSER, extensionRegistry); - if (subBuilder != null) { - subBuilder.mergeFrom(header_); - header_ = subBuilder.buildPartial(); - } - bitField0_ |= 0x00000001; - break; - } - case 18: { - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder subBuilder = null; - if (((bitField0_ & 0x00000002) == 0x00000002)) { - subBuilder = statement_.toBuilder(); - } - statement_ = input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.PARSER, extensionRegistry); - if (subBuilder != null) { - subBuilder.mergeFrom(statement_); - statement_ = subBuilder.buildPartial(); - } - bitField0_ |= 0x00000002; - break; - } - case 26: { - org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder subBuilder = null; - if (((bitField0_ & 0x00000004) == 0x00000004)) { - subBuilder = preference_.toBuilder(); - } - preference_ = input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.PARSER, extensionRegistry); - if (subBuilder != null) { - subBuilder.mergeFrom(preference_); - preference_ = subBuilder.buildPartial(); - } - bitField0_ |= 0x00000004; - break; - } - case 34: { - org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder subBuilder = null; - if (((bitField0_ & 0x00000008) == 0x00000008)) { - subBuilder = attachment_.toBuilder(); - } - attachment_ = input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.Attachment.PARSER, extensionRegistry); - if (subBuilder != null) { - subBuilder.mergeFrom(attachment_); - attachment_ = subBuilder.buildPartial(); - } - bitField0_ |= 0x00000008; - break; - } - case 42: { - org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder subBuilder = null; - if (((bitField0_ & 0x00000010) == 0x00000010)) { - subBuilder = version_.toBuilder(); - } - version_ = input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.PARSER, extensionRegistry); - if (subBuilder != null) { - subBuilder.mergeFrom(version_); - version_ = subBuilder.buildPartial(); - } - bitField0_ |= 0x00000010; - break; - } - case 48: { - bitField0_ |= 0x00000020; - end_ = input.readBool(); - break; - } - case 58: { - org.thoughtcrime.securesms.backup.BackupProtos.Avatar.Builder subBuilder = null; - if (((bitField0_ & 0x00000040) == 0x00000040)) { - subBuilder = avatar_.toBuilder(); - } - avatar_ = input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.Avatar.PARSER, extensionRegistry); - if (subBuilder != null) { - subBuilder.mergeFrom(avatar_); - avatar_ = subBuilder.buildPartial(); - } - bitField0_ |= 0x00000040; - break; - } - case 66: { - org.thoughtcrime.securesms.backup.BackupProtos.Sticker.Builder subBuilder = null; - if (((bitField0_ & 0x00000080) == 0x00000080)) { - subBuilder = sticker_.toBuilder(); - } - sticker_ = input.readMessage(org.thoughtcrime.securesms.backup.BackupProtos.Sticker.PARSER, extensionRegistry); - if (subBuilder != null) { - subBuilder.mergeFrom(sticker_); - sticker_ = subBuilder.buildPartial(); - } - bitField0_ |= 0x00000080; - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e.getMessage()).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_BackupFrame_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_BackupFrame_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.class, org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.Builder.class); - } - - public static com.google.protobuf.Parser PARSER = - new com.google.protobuf.AbstractParser() { - public BackupFrame parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new BackupFrame(input, extensionRegistry); - } - }; - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - private int bitField0_; - // optional .signal.Header header = 1; - public static final int HEADER_FIELD_NUMBER = 1; - private org.thoughtcrime.securesms.backup.BackupProtos.Header header_; - /** - * optional .signal.Header header = 1; - */ - public boolean hasHeader() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional .signal.Header header = 1; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.Header getHeader() { - return header_; - } - /** - * optional .signal.Header header = 1; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder getHeaderOrBuilder() { - return header_; - } - - // optional .signal.SqlStatement statement = 2; - public static final int STATEMENT_FIELD_NUMBER = 2; - private org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement statement_; - /** - * optional .signal.SqlStatement statement = 2; - */ - public boolean hasStatement() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional .signal.SqlStatement statement = 2; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement getStatement() { - return statement_; - } - /** - * optional .signal.SqlStatement statement = 2; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder getStatementOrBuilder() { - return statement_; - } - - // optional .signal.SharedPreference preference = 3; - public static final int PREFERENCE_FIELD_NUMBER = 3; - private org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference preference_; - /** - * optional .signal.SharedPreference preference = 3; - */ - public boolean hasPreference() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - /** - * optional .signal.SharedPreference preference = 3; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference getPreference() { - return preference_; - } - /** - * optional .signal.SharedPreference preference = 3; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder getPreferenceOrBuilder() { - return preference_; - } - - // optional .signal.Attachment attachment = 4; - public static final int ATTACHMENT_FIELD_NUMBER = 4; - private org.thoughtcrime.securesms.backup.BackupProtos.Attachment attachment_; - /** - * optional .signal.Attachment attachment = 4; - */ - public boolean hasAttachment() { - return ((bitField0_ & 0x00000008) == 0x00000008); - } - /** - * optional .signal.Attachment attachment = 4; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.Attachment getAttachment() { - return attachment_; - } - /** - * optional .signal.Attachment attachment = 4; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder getAttachmentOrBuilder() { - return attachment_; - } - - // optional .signal.DatabaseVersion version = 5; - public static final int VERSION_FIELD_NUMBER = 5; - private org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion version_; - /** - * optional .signal.DatabaseVersion version = 5; - */ - public boolean hasVersion() { - return ((bitField0_ & 0x00000010) == 0x00000010); - } - /** - * optional .signal.DatabaseVersion version = 5; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion getVersion() { - return version_; - } - /** - * optional .signal.DatabaseVersion version = 5; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder getVersionOrBuilder() { - return version_; - } - - // optional bool end = 6; - public static final int END_FIELD_NUMBER = 6; - private boolean end_; - /** - * optional bool end = 6; - */ - public boolean hasEnd() { - return ((bitField0_ & 0x00000020) == 0x00000020); - } - /** - * optional bool end = 6; - */ - public boolean getEnd() { - return end_; - } - - // optional .signal.Avatar avatar = 7; - public static final int AVATAR_FIELD_NUMBER = 7; - private org.thoughtcrime.securesms.backup.BackupProtos.Avatar avatar_; - /** - * optional .signal.Avatar avatar = 7; - */ - public boolean hasAvatar() { - return ((bitField0_ & 0x00000040) == 0x00000040); - } - /** - * optional .signal.Avatar avatar = 7; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.Avatar getAvatar() { - return avatar_; - } - /** - * optional .signal.Avatar avatar = 7; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.AvatarOrBuilder getAvatarOrBuilder() { - return avatar_; - } - - // optional .signal.Sticker sticker = 8; - public static final int STICKER_FIELD_NUMBER = 8; - private org.thoughtcrime.securesms.backup.BackupProtos.Sticker sticker_; - /** - * optional .signal.Sticker sticker = 8; - */ - public boolean hasSticker() { - return ((bitField0_ & 0x00000080) == 0x00000080); - } - /** - * optional .signal.Sticker sticker = 8; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.Sticker getSticker() { - return sticker_; - } - /** - * optional .signal.Sticker sticker = 8; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.StickerOrBuilder getStickerOrBuilder() { - return sticker_; - } - - private void initFields() { - header_ = org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance(); - statement_ = org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance(); - preference_ = org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance(); - attachment_ = org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance(); - version_ = org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance(); - end_ = false; - avatar_ = org.thoughtcrime.securesms.backup.BackupProtos.Avatar.getDefaultInstance(); - sticker_ = org.thoughtcrime.securesms.backup.BackupProtos.Sticker.getDefaultInstance(); - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeMessage(1, header_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeMessage(2, statement_); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeMessage(3, preference_); - } - if (((bitField0_ & 0x00000008) == 0x00000008)) { - output.writeMessage(4, attachment_); - } - if (((bitField0_ & 0x00000010) == 0x00000010)) { - output.writeMessage(5, version_); - } - if (((bitField0_ & 0x00000020) == 0x00000020)) { - output.writeBool(6, end_); - } - if (((bitField0_ & 0x00000040) == 0x00000040)) { - output.writeMessage(7, avatar_); - } - if (((bitField0_ & 0x00000080) == 0x00000080)) { - output.writeMessage(8, sticker_); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, header_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, statement_); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, preference_); - } - if (((bitField0_ & 0x00000008) == 0x00000008)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, attachment_); - } - if (((bitField0_ & 0x00000010) == 0x00000010)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, version_); - } - if (((bitField0_ & 0x00000020) == 0x00000020)) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(6, end_); - } - if (((bitField0_ & 0x00000040) == 0x00000040)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(7, avatar_); - } - if (((bitField0_ & 0x00000080) == 0x00000080)) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(8, sticker_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code signal.BackupFrame} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements org.thoughtcrime.securesms.backup.BackupProtos.BackupFrameOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_BackupFrame_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_BackupFrame_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.class, org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.Builder.class); - } - - // Construct using org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - getHeaderFieldBuilder(); - getStatementFieldBuilder(); - getPreferenceFieldBuilder(); - getAttachmentFieldBuilder(); - getVersionFieldBuilder(); - getAvatarFieldBuilder(); - getStickerFieldBuilder(); - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - if (headerBuilder_ == null) { - header_ = org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance(); - } else { - headerBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000001); - if (statementBuilder_ == null) { - statement_ = org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance(); - } else { - statementBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000002); - if (preferenceBuilder_ == null) { - preference_ = org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance(); - } else { - preferenceBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000004); - if (attachmentBuilder_ == null) { - attachment_ = org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance(); - } else { - attachmentBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000008); - if (versionBuilder_ == null) { - version_ = org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance(); - } else { - versionBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000010); - end_ = false; - bitField0_ = (bitField0_ & ~0x00000020); - if (avatarBuilder_ == null) { - avatar_ = org.thoughtcrime.securesms.backup.BackupProtos.Avatar.getDefaultInstance(); - } else { - avatarBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000040); - if (stickerBuilder_ == null) { - sticker_ = org.thoughtcrime.securesms.backup.BackupProtos.Sticker.getDefaultInstance(); - } else { - stickerBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000080); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.internal_static_signal_BackupFrame_descriptor; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame getDefaultInstanceForType() { - return org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.getDefaultInstance(); - } - - public org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame build() { - org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame buildPartial() { - org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame result = new org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - if (headerBuilder_ == null) { - result.header_ = header_; - } else { - result.header_ = headerBuilder_.build(); - } - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - if (statementBuilder_ == null) { - result.statement_ = statement_; - } else { - result.statement_ = statementBuilder_.build(); - } - if (((from_bitField0_ & 0x00000004) == 0x00000004)) { - to_bitField0_ |= 0x00000004; - } - if (preferenceBuilder_ == null) { - result.preference_ = preference_; - } else { - result.preference_ = preferenceBuilder_.build(); - } - if (((from_bitField0_ & 0x00000008) == 0x00000008)) { - to_bitField0_ |= 0x00000008; - } - if (attachmentBuilder_ == null) { - result.attachment_ = attachment_; - } else { - result.attachment_ = attachmentBuilder_.build(); - } - if (((from_bitField0_ & 0x00000010) == 0x00000010)) { - to_bitField0_ |= 0x00000010; - } - if (versionBuilder_ == null) { - result.version_ = version_; - } else { - result.version_ = versionBuilder_.build(); - } - if (((from_bitField0_ & 0x00000020) == 0x00000020)) { - to_bitField0_ |= 0x00000020; - } - result.end_ = end_; - if (((from_bitField0_ & 0x00000040) == 0x00000040)) { - to_bitField0_ |= 0x00000040; - } - if (avatarBuilder_ == null) { - result.avatar_ = avatar_; - } else { - result.avatar_ = avatarBuilder_.build(); - } - if (((from_bitField0_ & 0x00000080) == 0x00000080)) { - to_bitField0_ |= 0x00000080; - } - if (stickerBuilder_ == null) { - result.sticker_ = sticker_; - } else { - result.sticker_ = stickerBuilder_.build(); - } - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame) { - return mergeFrom((org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame other) { - if (other == org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame.getDefaultInstance()) return this; - if (other.hasHeader()) { - mergeHeader(other.getHeader()); - } - if (other.hasStatement()) { - mergeStatement(other.getStatement()); - } - if (other.hasPreference()) { - mergePreference(other.getPreference()); - } - if (other.hasAttachment()) { - mergeAttachment(other.getAttachment()); - } - if (other.hasVersion()) { - mergeVersion(other.getVersion()); - } - if (other.hasEnd()) { - setEnd(other.getEnd()); - } - if (other.hasAvatar()) { - mergeAvatar(other.getAvatar()); - } - if (other.hasSticker()) { - mergeSticker(other.getSticker()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - // optional .signal.Header header = 1; - private org.thoughtcrime.securesms.backup.BackupProtos.Header header_ = org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance(); - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.Header, org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder, org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder> headerBuilder_; - /** - * optional .signal.Header header = 1; - */ - public boolean hasHeader() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional .signal.Header header = 1; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.Header getHeader() { - if (headerBuilder_ == null) { - return header_; - } else { - return headerBuilder_.getMessage(); - } - } - /** - * optional .signal.Header header = 1; - */ - public Builder setHeader(org.thoughtcrime.securesms.backup.BackupProtos.Header value) { - if (headerBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - header_ = value; - onChanged(); - } else { - headerBuilder_.setMessage(value); - } - bitField0_ |= 0x00000001; - return this; - } - /** - * optional .signal.Header header = 1; - */ - public Builder setHeader( - org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder builderForValue) { - if (headerBuilder_ == null) { - header_ = builderForValue.build(); - onChanged(); - } else { - headerBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000001; - return this; - } - /** - * optional .signal.Header header = 1; - */ - public Builder mergeHeader(org.thoughtcrime.securesms.backup.BackupProtos.Header value) { - if (headerBuilder_ == null) { - if (((bitField0_ & 0x00000001) == 0x00000001) && - header_ != org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance()) { - header_ = - org.thoughtcrime.securesms.backup.BackupProtos.Header.newBuilder(header_).mergeFrom(value).buildPartial(); - } else { - header_ = value; - } - onChanged(); - } else { - headerBuilder_.mergeFrom(value); - } - bitField0_ |= 0x00000001; - return this; - } - /** - * optional .signal.Header header = 1; - */ - public Builder clearHeader() { - if (headerBuilder_ == null) { - header_ = org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance(); - onChanged(); - } else { - headerBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000001); - return this; - } - /** - * optional .signal.Header header = 1; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder getHeaderBuilder() { - bitField0_ |= 0x00000001; - onChanged(); - return getHeaderFieldBuilder().getBuilder(); - } - /** - * optional .signal.Header header = 1; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder getHeaderOrBuilder() { - if (headerBuilder_ != null) { - return headerBuilder_.getMessageOrBuilder(); - } else { - return header_; - } - } - /** - * optional .signal.Header header = 1; - */ - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.Header, org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder, org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder> - getHeaderFieldBuilder() { - if (headerBuilder_ == null) { - headerBuilder_ = new com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.Header, org.thoughtcrime.securesms.backup.BackupProtos.Header.Builder, org.thoughtcrime.securesms.backup.BackupProtos.HeaderOrBuilder>( - header_, - getParentForChildren(), - isClean()); - header_ = null; - } - return headerBuilder_; - } - - // optional .signal.SqlStatement statement = 2; - private org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement statement_ = org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance(); - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder> statementBuilder_; - /** - * optional .signal.SqlStatement statement = 2; - */ - public boolean hasStatement() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional .signal.SqlStatement statement = 2; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement getStatement() { - if (statementBuilder_ == null) { - return statement_; - } else { - return statementBuilder_.getMessage(); - } - } - /** - * optional .signal.SqlStatement statement = 2; - */ - public Builder setStatement(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement value) { - if (statementBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - statement_ = value; - onChanged(); - } else { - statementBuilder_.setMessage(value); - } - bitField0_ |= 0x00000002; - return this; - } - /** - * optional .signal.SqlStatement statement = 2; - */ - public Builder setStatement( - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder builderForValue) { - if (statementBuilder_ == null) { - statement_ = builderForValue.build(); - onChanged(); - } else { - statementBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000002; - return this; - } - /** - * optional .signal.SqlStatement statement = 2; - */ - public Builder mergeStatement(org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement value) { - if (statementBuilder_ == null) { - if (((bitField0_ & 0x00000002) == 0x00000002) && - statement_ != org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance()) { - statement_ = - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.newBuilder(statement_).mergeFrom(value).buildPartial(); - } else { - statement_ = value; - } - onChanged(); - } else { - statementBuilder_.mergeFrom(value); - } - bitField0_ |= 0x00000002; - return this; - } - /** - * optional .signal.SqlStatement statement = 2; - */ - public Builder clearStatement() { - if (statementBuilder_ == null) { - statement_ = org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance(); - onChanged(); - } else { - statementBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000002); - return this; - } - /** - * optional .signal.SqlStatement statement = 2; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder getStatementBuilder() { - bitField0_ |= 0x00000002; - onChanged(); - return getStatementFieldBuilder().getBuilder(); - } - /** - * optional .signal.SqlStatement statement = 2; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder getStatementOrBuilder() { - if (statementBuilder_ != null) { - return statementBuilder_.getMessageOrBuilder(); - } else { - return statement_; - } - } - /** - * optional .signal.SqlStatement statement = 2; - */ - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder> - getStatementFieldBuilder() { - if (statementBuilder_ == null) { - statementBuilder_ = new com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SqlStatementOrBuilder>( - statement_, - getParentForChildren(), - isClean()); - statement_ = null; - } - return statementBuilder_; - } - - // optional .signal.SharedPreference preference = 3; - private org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference preference_ = org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance(); - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder> preferenceBuilder_; - /** - * optional .signal.SharedPreference preference = 3; - */ - public boolean hasPreference() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - /** - * optional .signal.SharedPreference preference = 3; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference getPreference() { - if (preferenceBuilder_ == null) { - return preference_; - } else { - return preferenceBuilder_.getMessage(); - } - } - /** - * optional .signal.SharedPreference preference = 3; - */ - public Builder setPreference(org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference value) { - if (preferenceBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - preference_ = value; - onChanged(); - } else { - preferenceBuilder_.setMessage(value); - } - bitField0_ |= 0x00000004; - return this; - } - /** - * optional .signal.SharedPreference preference = 3; - */ - public Builder setPreference( - org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder builderForValue) { - if (preferenceBuilder_ == null) { - preference_ = builderForValue.build(); - onChanged(); - } else { - preferenceBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000004; - return this; - } - /** - * optional .signal.SharedPreference preference = 3; - */ - public Builder mergePreference(org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference value) { - if (preferenceBuilder_ == null) { - if (((bitField0_ & 0x00000004) == 0x00000004) && - preference_ != org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance()) { - preference_ = - org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.newBuilder(preference_).mergeFrom(value).buildPartial(); - } else { - preference_ = value; - } - onChanged(); - } else { - preferenceBuilder_.mergeFrom(value); - } - bitField0_ |= 0x00000004; - return this; - } - /** - * optional .signal.SharedPreference preference = 3; - */ - public Builder clearPreference() { - if (preferenceBuilder_ == null) { - preference_ = org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.getDefaultInstance(); - onChanged(); - } else { - preferenceBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000004); - return this; - } - /** - * optional .signal.SharedPreference preference = 3; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder getPreferenceBuilder() { - bitField0_ |= 0x00000004; - onChanged(); - return getPreferenceFieldBuilder().getBuilder(); - } - /** - * optional .signal.SharedPreference preference = 3; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder getPreferenceOrBuilder() { - if (preferenceBuilder_ != null) { - return preferenceBuilder_.getMessageOrBuilder(); - } else { - return preference_; - } - } - /** - * optional .signal.SharedPreference preference = 3; - */ - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder> - getPreferenceFieldBuilder() { - if (preferenceBuilder_ == null) { - preferenceBuilder_ = new com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference.Builder, org.thoughtcrime.securesms.backup.BackupProtos.SharedPreferenceOrBuilder>( - preference_, - getParentForChildren(), - isClean()); - preference_ = null; - } - return preferenceBuilder_; - } - - // optional .signal.Attachment attachment = 4; - private org.thoughtcrime.securesms.backup.BackupProtos.Attachment attachment_ = org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance(); - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.Attachment, org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder, org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder> attachmentBuilder_; - /** - * optional .signal.Attachment attachment = 4; - */ - public boolean hasAttachment() { - return ((bitField0_ & 0x00000008) == 0x00000008); - } - /** - * optional .signal.Attachment attachment = 4; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.Attachment getAttachment() { - if (attachmentBuilder_ == null) { - return attachment_; - } else { - return attachmentBuilder_.getMessage(); - } - } - /** - * optional .signal.Attachment attachment = 4; - */ - public Builder setAttachment(org.thoughtcrime.securesms.backup.BackupProtos.Attachment value) { - if (attachmentBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - attachment_ = value; - onChanged(); - } else { - attachmentBuilder_.setMessage(value); - } - bitField0_ |= 0x00000008; - return this; - } - /** - * optional .signal.Attachment attachment = 4; - */ - public Builder setAttachment( - org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder builderForValue) { - if (attachmentBuilder_ == null) { - attachment_ = builderForValue.build(); - onChanged(); - } else { - attachmentBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000008; - return this; - } - /** - * optional .signal.Attachment attachment = 4; - */ - public Builder mergeAttachment(org.thoughtcrime.securesms.backup.BackupProtos.Attachment value) { - if (attachmentBuilder_ == null) { - if (((bitField0_ & 0x00000008) == 0x00000008) && - attachment_ != org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance()) { - attachment_ = - org.thoughtcrime.securesms.backup.BackupProtos.Attachment.newBuilder(attachment_).mergeFrom(value).buildPartial(); - } else { - attachment_ = value; - } - onChanged(); - } else { - attachmentBuilder_.mergeFrom(value); - } - bitField0_ |= 0x00000008; - return this; - } - /** - * optional .signal.Attachment attachment = 4; - */ - public Builder clearAttachment() { - if (attachmentBuilder_ == null) { - attachment_ = org.thoughtcrime.securesms.backup.BackupProtos.Attachment.getDefaultInstance(); - onChanged(); - } else { - attachmentBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000008); - return this; - } - /** - * optional .signal.Attachment attachment = 4; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder getAttachmentBuilder() { - bitField0_ |= 0x00000008; - onChanged(); - return getAttachmentFieldBuilder().getBuilder(); - } - /** - * optional .signal.Attachment attachment = 4; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder getAttachmentOrBuilder() { - if (attachmentBuilder_ != null) { - return attachmentBuilder_.getMessageOrBuilder(); - } else { - return attachment_; - } - } - /** - * optional .signal.Attachment attachment = 4; - */ - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.Attachment, org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder, org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder> - getAttachmentFieldBuilder() { - if (attachmentBuilder_ == null) { - attachmentBuilder_ = new com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.Attachment, org.thoughtcrime.securesms.backup.BackupProtos.Attachment.Builder, org.thoughtcrime.securesms.backup.BackupProtos.AttachmentOrBuilder>( - attachment_, - getParentForChildren(), - isClean()); - attachment_ = null; - } - return attachmentBuilder_; - } - - // optional .signal.DatabaseVersion version = 5; - private org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion version_ = org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance(); - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder> versionBuilder_; - /** - * optional .signal.DatabaseVersion version = 5; - */ - public boolean hasVersion() { - return ((bitField0_ & 0x00000010) == 0x00000010); - } - /** - * optional .signal.DatabaseVersion version = 5; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion getVersion() { - if (versionBuilder_ == null) { - return version_; - } else { - return versionBuilder_.getMessage(); - } - } - /** - * optional .signal.DatabaseVersion version = 5; - */ - public Builder setVersion(org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion value) { - if (versionBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - version_ = value; - onChanged(); - } else { - versionBuilder_.setMessage(value); - } - bitField0_ |= 0x00000010; - return this; - } - /** - * optional .signal.DatabaseVersion version = 5; - */ - public Builder setVersion( - org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder builderForValue) { - if (versionBuilder_ == null) { - version_ = builderForValue.build(); - onChanged(); - } else { - versionBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000010; - return this; - } - /** - * optional .signal.DatabaseVersion version = 5; - */ - public Builder mergeVersion(org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion value) { - if (versionBuilder_ == null) { - if (((bitField0_ & 0x00000010) == 0x00000010) && - version_ != org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance()) { - version_ = - org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.newBuilder(version_).mergeFrom(value).buildPartial(); - } else { - version_ = value; - } - onChanged(); - } else { - versionBuilder_.mergeFrom(value); - } - bitField0_ |= 0x00000010; - return this; - } - /** - * optional .signal.DatabaseVersion version = 5; - */ - public Builder clearVersion() { - if (versionBuilder_ == null) { - version_ = org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.getDefaultInstance(); - onChanged(); - } else { - versionBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000010); - return this; - } - /** - * optional .signal.DatabaseVersion version = 5; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder getVersionBuilder() { - bitField0_ |= 0x00000010; - onChanged(); - return getVersionFieldBuilder().getBuilder(); - } - /** - * optional .signal.DatabaseVersion version = 5; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder getVersionOrBuilder() { - if (versionBuilder_ != null) { - return versionBuilder_.getMessageOrBuilder(); - } else { - return version_; - } - } - /** - * optional .signal.DatabaseVersion version = 5; - */ - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder> - getVersionFieldBuilder() { - if (versionBuilder_ == null) { - versionBuilder_ = new com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion.Builder, org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersionOrBuilder>( - version_, - getParentForChildren(), - isClean()); - version_ = null; - } - return versionBuilder_; - } - - // optional bool end = 6; - private boolean end_ ; - /** - * optional bool end = 6; - */ - public boolean hasEnd() { - return ((bitField0_ & 0x00000020) == 0x00000020); - } - /** - * optional bool end = 6; - */ - public boolean getEnd() { - return end_; - } - /** - * optional bool end = 6; - */ - public Builder setEnd(boolean value) { - bitField0_ |= 0x00000020; - end_ = value; - onChanged(); - return this; - } - /** - * optional bool end = 6; - */ - public Builder clearEnd() { - bitField0_ = (bitField0_ & ~0x00000020); - end_ = false; - onChanged(); - return this; - } - - // optional .signal.Avatar avatar = 7; - private org.thoughtcrime.securesms.backup.BackupProtos.Avatar avatar_ = org.thoughtcrime.securesms.backup.BackupProtos.Avatar.getDefaultInstance(); - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.Avatar, org.thoughtcrime.securesms.backup.BackupProtos.Avatar.Builder, org.thoughtcrime.securesms.backup.BackupProtos.AvatarOrBuilder> avatarBuilder_; - /** - * optional .signal.Avatar avatar = 7; - */ - public boolean hasAvatar() { - return ((bitField0_ & 0x00000040) == 0x00000040); - } - /** - * optional .signal.Avatar avatar = 7; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.Avatar getAvatar() { - if (avatarBuilder_ == null) { - return avatar_; - } else { - return avatarBuilder_.getMessage(); - } - } - /** - * optional .signal.Avatar avatar = 7; - */ - public Builder setAvatar(org.thoughtcrime.securesms.backup.BackupProtos.Avatar value) { - if (avatarBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - avatar_ = value; - onChanged(); - } else { - avatarBuilder_.setMessage(value); - } - bitField0_ |= 0x00000040; - return this; - } - /** - * optional .signal.Avatar avatar = 7; - */ - public Builder setAvatar( - org.thoughtcrime.securesms.backup.BackupProtos.Avatar.Builder builderForValue) { - if (avatarBuilder_ == null) { - avatar_ = builderForValue.build(); - onChanged(); - } else { - avatarBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000040; - return this; - } - /** - * optional .signal.Avatar avatar = 7; - */ - public Builder mergeAvatar(org.thoughtcrime.securesms.backup.BackupProtos.Avatar value) { - if (avatarBuilder_ == null) { - if (((bitField0_ & 0x00000040) == 0x00000040) && - avatar_ != org.thoughtcrime.securesms.backup.BackupProtos.Avatar.getDefaultInstance()) { - avatar_ = - org.thoughtcrime.securesms.backup.BackupProtos.Avatar.newBuilder(avatar_).mergeFrom(value).buildPartial(); - } else { - avatar_ = value; - } - onChanged(); - } else { - avatarBuilder_.mergeFrom(value); - } - bitField0_ |= 0x00000040; - return this; - } - /** - * optional .signal.Avatar avatar = 7; - */ - public Builder clearAvatar() { - if (avatarBuilder_ == null) { - avatar_ = org.thoughtcrime.securesms.backup.BackupProtos.Avatar.getDefaultInstance(); - onChanged(); - } else { - avatarBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000040); - return this; - } - /** - * optional .signal.Avatar avatar = 7; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.Avatar.Builder getAvatarBuilder() { - bitField0_ |= 0x00000040; - onChanged(); - return getAvatarFieldBuilder().getBuilder(); - } - /** - * optional .signal.Avatar avatar = 7; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.AvatarOrBuilder getAvatarOrBuilder() { - if (avatarBuilder_ != null) { - return avatarBuilder_.getMessageOrBuilder(); - } else { - return avatar_; - } - } - /** - * optional .signal.Avatar avatar = 7; - */ - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.Avatar, org.thoughtcrime.securesms.backup.BackupProtos.Avatar.Builder, org.thoughtcrime.securesms.backup.BackupProtos.AvatarOrBuilder> - getAvatarFieldBuilder() { - if (avatarBuilder_ == null) { - avatarBuilder_ = new com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.Avatar, org.thoughtcrime.securesms.backup.BackupProtos.Avatar.Builder, org.thoughtcrime.securesms.backup.BackupProtos.AvatarOrBuilder>( - avatar_, - getParentForChildren(), - isClean()); - avatar_ = null; - } - return avatarBuilder_; - } - - // optional .signal.Sticker sticker = 8; - private org.thoughtcrime.securesms.backup.BackupProtos.Sticker sticker_ = org.thoughtcrime.securesms.backup.BackupProtos.Sticker.getDefaultInstance(); - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.Sticker, org.thoughtcrime.securesms.backup.BackupProtos.Sticker.Builder, org.thoughtcrime.securesms.backup.BackupProtos.StickerOrBuilder> stickerBuilder_; - /** - * optional .signal.Sticker sticker = 8; - */ - public boolean hasSticker() { - return ((bitField0_ & 0x00000080) == 0x00000080); - } - /** - * optional .signal.Sticker sticker = 8; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.Sticker getSticker() { - if (stickerBuilder_ == null) { - return sticker_; - } else { - return stickerBuilder_.getMessage(); - } - } - /** - * optional .signal.Sticker sticker = 8; - */ - public Builder setSticker(org.thoughtcrime.securesms.backup.BackupProtos.Sticker value) { - if (stickerBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - sticker_ = value; - onChanged(); - } else { - stickerBuilder_.setMessage(value); - } - bitField0_ |= 0x00000080; - return this; - } - /** - * optional .signal.Sticker sticker = 8; - */ - public Builder setSticker( - org.thoughtcrime.securesms.backup.BackupProtos.Sticker.Builder builderForValue) { - if (stickerBuilder_ == null) { - sticker_ = builderForValue.build(); - onChanged(); - } else { - stickerBuilder_.setMessage(builderForValue.build()); - } - bitField0_ |= 0x00000080; - return this; - } - /** - * optional .signal.Sticker sticker = 8; - */ - public Builder mergeSticker(org.thoughtcrime.securesms.backup.BackupProtos.Sticker value) { - if (stickerBuilder_ == null) { - if (((bitField0_ & 0x00000080) == 0x00000080) && - sticker_ != org.thoughtcrime.securesms.backup.BackupProtos.Sticker.getDefaultInstance()) { - sticker_ = - org.thoughtcrime.securesms.backup.BackupProtos.Sticker.newBuilder(sticker_).mergeFrom(value).buildPartial(); - } else { - sticker_ = value; - } - onChanged(); - } else { - stickerBuilder_.mergeFrom(value); - } - bitField0_ |= 0x00000080; - return this; - } - /** - * optional .signal.Sticker sticker = 8; - */ - public Builder clearSticker() { - if (stickerBuilder_ == null) { - sticker_ = org.thoughtcrime.securesms.backup.BackupProtos.Sticker.getDefaultInstance(); - onChanged(); - } else { - stickerBuilder_.clear(); - } - bitField0_ = (bitField0_ & ~0x00000080); - return this; - } - /** - * optional .signal.Sticker sticker = 8; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.Sticker.Builder getStickerBuilder() { - bitField0_ |= 0x00000080; - onChanged(); - return getStickerFieldBuilder().getBuilder(); - } - /** - * optional .signal.Sticker sticker = 8; - */ - public org.thoughtcrime.securesms.backup.BackupProtos.StickerOrBuilder getStickerOrBuilder() { - if (stickerBuilder_ != null) { - return stickerBuilder_.getMessageOrBuilder(); - } else { - return sticker_; - } - } - /** - * optional .signal.Sticker sticker = 8; - */ - private com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.Sticker, org.thoughtcrime.securesms.backup.BackupProtos.Sticker.Builder, org.thoughtcrime.securesms.backup.BackupProtos.StickerOrBuilder> - getStickerFieldBuilder() { - if (stickerBuilder_ == null) { - stickerBuilder_ = new com.google.protobuf.SingleFieldBuilder< - org.thoughtcrime.securesms.backup.BackupProtos.Sticker, org.thoughtcrime.securesms.backup.BackupProtos.Sticker.Builder, org.thoughtcrime.securesms.backup.BackupProtos.StickerOrBuilder>( - sticker_, - getParentForChildren(), - isClean()); - sticker_ = null; - } - return stickerBuilder_; - } - - // @@protoc_insertion_point(builder_scope:signal.BackupFrame) - } - - static { - defaultInstance = new BackupFrame(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:signal.BackupFrame) - } - - private static com.google.protobuf.Descriptors.Descriptor - internal_static_signal_SqlStatement_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_signal_SqlStatement_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_signal_SqlStatement_SqlParameter_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_signal_SqlStatement_SqlParameter_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_signal_SharedPreference_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_signal_SharedPreference_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_signal_Attachment_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_signal_Attachment_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_signal_Sticker_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_signal_Sticker_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_signal_Avatar_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_signal_Avatar_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_signal_DatabaseVersion_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_signal_DatabaseVersion_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_signal_Header_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_signal_Header_fieldAccessorTable; - private static com.google.protobuf.Descriptors.Descriptor - internal_static_signal_BackupFrame_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_signal_BackupFrame_fieldAccessorTable; - - public static com.google.protobuf.Descriptors.FileDescriptor - getDescriptor() { - return descriptor; - } - private static com.google.protobuf.Descriptors.FileDescriptor - descriptor; - static { - java.lang.String[] descriptorData = { - "\n\rBackups.proto\022\006signal\"\342\001\n\014SqlStatement" + - "\022\021\n\tstatement\030\001 \001(\t\0225\n\nparameters\030\002 \003(\0132" + - "!.signal.SqlStatement.SqlParameter\032\207\001\n\014S" + - "qlParameter\022\026\n\016stringParamter\030\001 \001(\t\022\030\n\020i" + - "ntegerParameter\030\002 \001(\004\022\027\n\017doubleParameter" + - "\030\003 \001(\001\022\025\n\rblobParameter\030\004 \001(\014\022\025\n\rnullpar" + - "ameter\030\005 \001(\010\"<\n\020SharedPreference\022\014\n\004file" + - "\030\001 \001(\t\022\013\n\003key\030\002 \001(\t\022\r\n\005value\030\003 \001(\t\"A\n\nAt" + - "tachment\022\r\n\005rowId\030\001 \001(\004\022\024\n\014attachmentId\030" + - "\002 \001(\004\022\016\n\006length\030\003 \001(\r\"(\n\007Sticker\022\r\n\005rowI", - "d\030\001 \001(\004\022\016\n\006length\030\002 \001(\r\"&\n\006Avatar\022\014\n\004nam" + - "e\030\001 \001(\t\022\016\n\006length\030\002 \001(\r\"\"\n\017DatabaseVersi" + - "on\022\017\n\007version\030\001 \001(\r\"\"\n\006Header\022\n\n\002iv\030\001 \001(" + - "\014\022\014\n\004salt\030\002 \001(\014\"\245\002\n\013BackupFrame\022\036\n\006heade" + - "r\030\001 \001(\0132\016.signal.Header\022\'\n\tstatement\030\002 \001" + - "(\0132\024.signal.SqlStatement\022,\n\npreference\030\003" + - " \001(\0132\030.signal.SharedPreference\022&\n\nattach" + - "ment\030\004 \001(\0132\022.signal.Attachment\022(\n\007versio" + - "n\030\005 \001(\0132\027.signal.DatabaseVersion\022\013\n\003end\030" + - "\006 \001(\010\022\036\n\006avatar\030\007 \001(\0132\016.signal.Avatar\022 \n", - "\007sticker\030\010 \001(\0132\017.signal.StickerB1\n!org.t" + - "houghtcrime.securesms.backupB\014BackupProt" + - "os" - }; - com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { - public com.google.protobuf.ExtensionRegistry assignDescriptors( - com.google.protobuf.Descriptors.FileDescriptor root) { - descriptor = root; - internal_static_signal_SqlStatement_descriptor = - getDescriptor().getMessageTypes().get(0); - internal_static_signal_SqlStatement_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_signal_SqlStatement_descriptor, - new java.lang.String[] { "Statement", "Parameters", }); - internal_static_signal_SqlStatement_SqlParameter_descriptor = - internal_static_signal_SqlStatement_descriptor.getNestedTypes().get(0); - internal_static_signal_SqlStatement_SqlParameter_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_signal_SqlStatement_SqlParameter_descriptor, - new java.lang.String[] { "StringParamter", "IntegerParameter", "DoubleParameter", "BlobParameter", "Nullparameter", }); - internal_static_signal_SharedPreference_descriptor = - getDescriptor().getMessageTypes().get(1); - internal_static_signal_SharedPreference_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_signal_SharedPreference_descriptor, - new java.lang.String[] { "File", "Key", "Value", }); - internal_static_signal_Attachment_descriptor = - getDescriptor().getMessageTypes().get(2); - internal_static_signal_Attachment_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_signal_Attachment_descriptor, - new java.lang.String[] { "RowId", "AttachmentId", "Length", }); - internal_static_signal_Sticker_descriptor = - getDescriptor().getMessageTypes().get(3); - internal_static_signal_Sticker_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_signal_Sticker_descriptor, - new java.lang.String[] { "RowId", "Length", }); - internal_static_signal_Avatar_descriptor = - getDescriptor().getMessageTypes().get(4); - internal_static_signal_Avatar_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_signal_Avatar_descriptor, - new java.lang.String[] { "Name", "Length", }); - internal_static_signal_DatabaseVersion_descriptor = - getDescriptor().getMessageTypes().get(5); - internal_static_signal_DatabaseVersion_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_signal_DatabaseVersion_descriptor, - new java.lang.String[] { "Version", }); - internal_static_signal_Header_descriptor = - getDescriptor().getMessageTypes().get(6); - internal_static_signal_Header_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_signal_Header_descriptor, - new java.lang.String[] { "Iv", "Salt", }); - internal_static_signal_BackupFrame_descriptor = - getDescriptor().getMessageTypes().get(7); - internal_static_signal_BackupFrame_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_signal_BackupFrame_descriptor, - new java.lang.String[] { "Header", "Statement", "Preference", "Attachment", "Version", "End", "Avatar", "Sticker", }); - return null; - } - }; - com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - }, assigner); - } - - // @@protoc_insertion_point(outer_class_scope) -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt deleted file mode 100644 index 6b5d47a2e6..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt +++ /dev/null @@ -1,447 +0,0 @@ -package org.thoughtcrime.securesms.backup - -import android.content.Context -import android.database.Cursor -import android.net.Uri -import android.text.TextUtils -import androidx.annotation.WorkerThread -import com.annimon.stream.function.Consumer -import com.annimon.stream.function.Predicate -import com.google.protobuf.ByteString -import net.zetetic.database.sqlcipher.SQLiteDatabase -import org.greenrobot.eventbus.EventBus -import org.session.libsession.avatars.AvatarHelper -import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId -import org.session.libsession.utilities.Conversions -import org.session.libsession.utilities.Util -import org.session.libsignal.crypto.kdf.HKDFv3 -import org.session.libsignal.utilities.ByteUtil -import org.session.libsignal.utilities.Log -import org.thoughtcrime.securesms.backup.BackupProtos.Attachment -import org.thoughtcrime.securesms.backup.BackupProtos.Avatar -import org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame -import org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion -import org.thoughtcrime.securesms.backup.BackupProtos.Header -import org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference -import org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement -import org.thoughtcrime.securesms.backup.BackupProtos.Sticker -import org.thoughtcrime.securesms.crypto.AttachmentSecret -import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream -import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream -import org.thoughtcrime.securesms.database.AttachmentDatabase -import org.thoughtcrime.securesms.database.GroupReceiptDatabase -import org.thoughtcrime.securesms.database.JobDatabase -import org.thoughtcrime.securesms.database.LokiAPIDatabase -import org.thoughtcrime.securesms.database.LokiBackupFilesDatabase -import org.thoughtcrime.securesms.database.MmsDatabase -import org.thoughtcrime.securesms.database.MmsSmsColumns -import org.thoughtcrime.securesms.database.PushDatabase -import org.thoughtcrime.securesms.database.SearchDatabase -import org.thoughtcrime.securesms.database.SmsDatabase -import org.thoughtcrime.securesms.util.BackupUtil -import java.io.Closeable -import java.io.File -import java.io.FileInputStream -import java.io.Flushable -import java.io.IOException -import java.io.InputStream -import java.io.OutputStream -import java.security.InvalidAlgorithmParameterException -import java.security.InvalidKeyException -import java.security.NoSuchAlgorithmException -import java.util.LinkedList -import javax.crypto.BadPaddingException -import javax.crypto.Cipher -import javax.crypto.IllegalBlockSizeException -import javax.crypto.Mac -import javax.crypto.NoSuchPaddingException -import javax.crypto.spec.IvParameterSpec -import javax.crypto.spec.SecretKeySpec - -object FullBackupExporter { - private val TAG = FullBackupExporter::class.java.simpleName - - @JvmStatic - @WorkerThread - @Throws(IOException::class) - fun export(context: Context, - attachmentSecret: AttachmentSecret, - input: SQLiteDatabase, - fileUri: Uri, - passphrase: String) { - - val baseOutputStream = context.contentResolver.openOutputStream(fileUri) - ?: throw IOException("Cannot open an output stream for the file URI: $fileUri") - - var count = 0 - try { - BackupFrameOutputStream(baseOutputStream, passphrase).use { outputStream -> - outputStream.writeDatabaseVersion(input.version) - val tables = exportSchema(input, outputStream) - for (table in tables) if (shouldExportTable(table)) { - count = when (table) { - SmsDatabase.TABLE_NAME, MmsDatabase.TABLE_NAME -> { - exportTable(table, input, outputStream, - { cursor: Cursor -> - cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsColumns.EXPIRES_IN)) <= 0 - }, - null, - count) - } - GroupReceiptDatabase.TABLE_NAME -> { - exportTable(table, input, outputStream, - { cursor: Cursor -> - isForNonExpiringMessage(input, cursor.getLong(cursor.getColumnIndexOrThrow(GroupReceiptDatabase.MMS_ID))) - }, - null, - count) - } - AttachmentDatabase.TABLE_NAME -> { - exportTable(table, input, outputStream, - { cursor: Cursor -> - isForNonExpiringMessage(input, cursor.getLong(cursor.getColumnIndexOrThrow(AttachmentDatabase.MMS_ID))) - }, - { cursor: Cursor -> - exportAttachment(attachmentSecret, cursor, outputStream) - }, - count) - } - else -> { - exportTable(table, input, outputStream, null, null, count) - } - } - } - for (preference in BackupUtil.getBackupRecords(context)) { - EventBus.getDefault().post(BackupEvent.createProgress(++count)) - outputStream.writePreferenceEntry(preference) - } - for (preference in BackupPreferences.getBackupRecords(context)) { - EventBus.getDefault().post(BackupEvent.createProgress(++count)) - outputStream.writePreferenceEntry(preference) - } - for (avatar in AvatarHelper.getAvatarFiles(context)) { - EventBus.getDefault().post(BackupEvent.createProgress(++count)) - outputStream.writeAvatar(avatar.name, FileInputStream(avatar), avatar.length()) - } - outputStream.writeEnd() - } - EventBus.getDefault().post(BackupEvent.createFinished()) - } catch (e: Exception) { - Log.e(TAG, "Failed to make full backup.", e) - EventBus.getDefault().post(BackupEvent.createFinished(e)) - throw e - } - } - - private inline fun shouldExportTable(table: String): Boolean { - return table != PushDatabase.TABLE_NAME && - - table != LokiBackupFilesDatabase.TABLE_NAME && - table != LokiAPIDatabase.openGroupProfilePictureTable && - - table != JobDatabase.Jobs.TABLE_NAME && - table != JobDatabase.Constraints.TABLE_NAME && - table != JobDatabase.Dependencies.TABLE_NAME && - - !table.startsWith(SearchDatabase.SMS_FTS_TABLE_NAME) && - !table.startsWith(SearchDatabase.MMS_FTS_TABLE_NAME) && - !table.startsWith("sqlite_") - } - - @Throws(IOException::class) - private fun exportSchema(input: SQLiteDatabase, outputStream: BackupFrameOutputStream): List { - val tables: MutableList = LinkedList() - input.rawQuery("SELECT sql, name, type FROM sqlite_master", null).use { cursor -> - while (cursor != null && cursor.moveToNext()) { - val sql = cursor.getString(0) - val name = cursor.getString(1) - val type = cursor.getString(2) - if (sql != null) { - val isSmsFtsSecretTable = name != null && name != SearchDatabase.SMS_FTS_TABLE_NAME && name.startsWith(SearchDatabase.SMS_FTS_TABLE_NAME) - val isMmsFtsSecretTable = name != null && name != SearchDatabase.MMS_FTS_TABLE_NAME && name.startsWith(SearchDatabase.MMS_FTS_TABLE_NAME) - if (!isSmsFtsSecretTable && !isMmsFtsSecretTable) { - if ("table" == type) { - tables.add(name) - } - outputStream.writeSql(SqlStatement.newBuilder().setStatement(cursor.getString(0)).build()) - } - } - } - } - return tables - } - - @Throws(IOException::class) - private fun exportTable(table: String, - input: SQLiteDatabase, - outputStream: BackupFrameOutputStream, - predicate: Predicate?, - postProcess: Consumer?, - count: Int): Int { - var count = count - val template = "INSERT INTO $table VALUES " - input.rawQuery("SELECT * FROM $table", null).use { cursor -> - while (cursor != null && cursor.moveToNext()) { - EventBus.getDefault().post(BackupEvent.createProgress(++count)) - if (predicate != null && !predicate.test(cursor)) continue - - val statement = StringBuilder(template) - val statementBuilder = SqlStatement.newBuilder() - statement.append('(') - for (i in 0 until cursor.columnCount) { - statement.append('?') - when (cursor.getType(i)) { - Cursor.FIELD_TYPE_STRING -> { - statementBuilder.addParameters(SqlStatement.SqlParameter.newBuilder() - .setStringParamter(cursor.getString(i))) - } - Cursor.FIELD_TYPE_FLOAT -> { - statementBuilder.addParameters(SqlStatement.SqlParameter.newBuilder() - .setDoubleParameter(cursor.getDouble(i))) - } - Cursor.FIELD_TYPE_INTEGER -> { - statementBuilder.addParameters(SqlStatement.SqlParameter.newBuilder() - .setIntegerParameter(cursor.getLong(i))) - } - Cursor.FIELD_TYPE_BLOB -> { - statementBuilder.addParameters(SqlStatement.SqlParameter.newBuilder() - .setBlobParameter(ByteString.copyFrom(cursor.getBlob(i)))) - } - Cursor.FIELD_TYPE_NULL -> { - statementBuilder.addParameters(SqlStatement.SqlParameter.newBuilder() - .setNullparameter(true)) - } - else -> { - throw AssertionError("unknown type?" + cursor.getType(i)) - } - } - if (i < cursor.columnCount - 1) { - statement.append(',') - } - } - statement.append(')') - outputStream.writeSql(statementBuilder.setStatement(statement.toString()).build()) - postProcess?.accept(cursor) - } - } - return count - } - - private fun exportAttachment(attachmentSecret: AttachmentSecret, cursor: Cursor, outputStream: BackupFrameOutputStream) { - try { - val rowId = cursor.getLong(cursor.getColumnIndexOrThrow(AttachmentDatabase.ROW_ID)) - val uniqueId = cursor.getLong(cursor.getColumnIndexOrThrow(AttachmentDatabase.UNIQUE_ID)) - var size = cursor.getLong(cursor.getColumnIndexOrThrow(AttachmentDatabase.SIZE)) - val data = cursor.getString(cursor.getColumnIndexOrThrow(AttachmentDatabase.DATA)) - val random = cursor.getBlob(cursor.getColumnIndexOrThrow(AttachmentDatabase.DATA_RANDOM)) - if (!TextUtils.isEmpty(data) && size <= 0) { - size = calculateVeryOldStreamLength(attachmentSecret, random, data) - } - if (!TextUtils.isEmpty(data) && size > 0) { - val inputStream: InputStream = if (random != null && random.size == 32) { - ModernDecryptingPartInputStream.createFor(attachmentSecret, random, File(data), 0) - } else { - ClassicDecryptingPartInputStream.createFor(attachmentSecret, File(data)) - } - outputStream.writeAttachment(AttachmentId(rowId, uniqueId), inputStream, size) - } - } catch (e: IOException) { - Log.w(TAG, e) - } - } - - @Throws(IOException::class) - private fun calculateVeryOldStreamLength(attachmentSecret: AttachmentSecret, random: ByteArray?, data: String): Long { - var result: Long = 0 - val inputStream: InputStream = if (random != null && random.size == 32) { - ModernDecryptingPartInputStream.createFor(attachmentSecret, random, File(data), 0) - } else { - ClassicDecryptingPartInputStream.createFor(attachmentSecret, File(data)) - } - var read: Int - val buffer = ByteArray(8192) - while (inputStream.read(buffer, 0, buffer.size).also { read = it } != -1) { - result += read.toLong() - } - return result - } - - private fun isForNonExpiringMessage(db: SQLiteDatabase, mmsId: Long): Boolean { - val columns = arrayOf(MmsSmsColumns.EXPIRES_IN) - val where = MmsSmsColumns.ID + " = ?" - val args = arrayOf(mmsId.toString()) - db.query(MmsDatabase.TABLE_NAME, columns, where, args, null, null, null).use { mmsCursor -> - if (mmsCursor != null && mmsCursor.moveToFirst()) { - return mmsCursor.getLong(0) == 0L - } - } - return false - } - - private class BackupFrameOutputStream : Closeable, Flushable { - - private val outputStream: OutputStream - private var cipher: Cipher - private var mac: Mac - private val cipherKey: ByteArray - private val macKey: ByteArray - private val iv: ByteArray - - private var counter: Int = 0 - - constructor(outputStream: OutputStream, passphrase: String) : super() { - try { - val salt = Util.getSecretBytes(32) - val key = BackupUtil.computeBackupKey(passphrase, salt) - val derived = HKDFv3().deriveSecrets(key, "Backup Export".toByteArray(), 64) - val split = ByteUtil.split(derived, 32, 32) - cipherKey = split[0] - macKey = split[1] - cipher = Cipher.getInstance("AES/CTR/NoPadding") - mac = Mac.getInstance("HmacSHA256") - this.outputStream = outputStream - iv = Util.getSecretBytes(16) - counter = Conversions.byteArrayToInt(iv) - mac.init(SecretKeySpec(macKey, "HmacSHA256")) - val header = BackupFrame.newBuilder().setHeader(Header.newBuilder() - .setIv(ByteString.copyFrom(iv)) - .setSalt(ByteString.copyFrom(salt))) - .build().toByteArray() - outputStream.write(Conversions.intToByteArray(header.size)) - outputStream.write(header) - } catch (e: Exception) { - when (e) { - is NoSuchAlgorithmException, - is NoSuchPaddingException, - is InvalidKeyException -> { - throw AssertionError(e) - } - else -> throw e - } - } - } - - @Throws(IOException::class) - fun writeSql(statement: SqlStatement) { - write(outputStream, BackupFrame.newBuilder().setStatement(statement).build()) - } - - @Throws(IOException::class) - fun writePreferenceEntry(preference: SharedPreference?) { - write(outputStream, BackupFrame.newBuilder().setPreference(preference).build()) - } - - @Throws(IOException::class) - fun writeAvatar(avatarName: String, inputStream: InputStream, size: Long) { - write(outputStream, BackupFrame.newBuilder() - .setAvatar(Avatar.newBuilder() - .setName(avatarName) - .setLength(Util.toIntExact(size)) - .build()) - .build()) - writeStream(inputStream) - } - - @Throws(IOException::class) - fun writeAttachment(attachmentId: AttachmentId, inputStream: InputStream, size: Long) { - write(outputStream, BackupFrame.newBuilder() - .setAttachment(Attachment.newBuilder() - .setRowId(attachmentId.rowId) - .setAttachmentId(attachmentId.uniqueId) - .setLength(Util.toIntExact(size)) - .build()) - .build()) - writeStream(inputStream) - } - - @Throws(IOException::class) - fun writeSticker(rowId: Long, inputStream: InputStream, size: Long) { - write(outputStream, BackupFrame.newBuilder() - .setSticker(Sticker.newBuilder() - .setRowId(rowId) - .setLength(Util.toIntExact(size)) - .build()) - .build()) - writeStream(inputStream) - } - - @Throws(IOException::class) - fun writeDatabaseVersion(version: Int) { - write(outputStream, BackupFrame.newBuilder() - .setVersion(DatabaseVersion.newBuilder().setVersion(version)) - .build()) - } - - @Throws(IOException::class) - fun writeEnd() { - write(outputStream, BackupFrame.newBuilder().setEnd(true).build()) - } - - @Throws(IOException::class) - private fun writeStream(inputStream: InputStream) { - try { - Conversions.intToByteArray(iv, 0, counter++) - cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(cipherKey, "AES"), IvParameterSpec(iv)) - mac.update(iv) - val buffer = ByteArray(8192) - var read: Int - while (inputStream.read(buffer).also { read = it } != -1) { - val ciphertext = cipher.update(buffer, 0, read) - if (ciphertext != null) { - outputStream.write(ciphertext) - mac.update(ciphertext) - } - } - val remainder = cipher.doFinal() - outputStream.write(remainder) - mac.update(remainder) - val attachmentDigest = mac.doFinal() - outputStream.write(attachmentDigest, 0, 10) - } catch (e: Exception) { - when (e) { - is InvalidKeyException, - is InvalidAlgorithmParameterException, - is IllegalBlockSizeException, - is BadPaddingException -> { - throw AssertionError(e) - } - else -> throw e - } - } - } - - @Throws(IOException::class) - private fun write(out: OutputStream, frame: BackupFrame) { - try { - Conversions.intToByteArray(iv, 0, counter++) - cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(cipherKey, "AES"), IvParameterSpec(iv)) - val frameCiphertext = cipher.doFinal(frame.toByteArray()) - val frameMac = mac.doFinal(frameCiphertext) - val length = Conversions.intToByteArray(frameCiphertext.size + 10) - out.write(length) - out.write(frameCiphertext) - out.write(frameMac, 0, 10) - } catch (e: Exception) { - when (e) { - is InvalidKeyException, - is InvalidAlgorithmParameterException, - is IllegalBlockSizeException, - is BadPaddingException -> { - throw AssertionError(e) - } - else -> throw e - } - } - } - - @Throws(IOException::class) - override fun flush() { - outputStream.flush() - } - - @Throws(IOException::class) - override fun close() { - outputStream.close() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupImporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupImporter.kt deleted file mode 100644 index b40c049bc2..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupImporter.kt +++ /dev/null @@ -1,352 +0,0 @@ -package org.thoughtcrime.securesms.backup - -import android.annotation.SuppressLint -import android.content.ContentValues -import android.content.Context -import android.net.Uri -import androidx.annotation.WorkerThread -import net.zetetic.database.sqlcipher.SQLiteDatabase -import org.greenrobot.eventbus.EventBus -import org.session.libsession.avatars.AvatarHelper -import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId -import org.session.libsession.utilities.Address -import org.session.libsession.utilities.Conversions -import org.session.libsession.utilities.Util -import org.session.libsignal.crypto.kdf.HKDFv3 -import org.session.libsignal.utilities.ByteUtil -import org.session.libsignal.utilities.Log -import org.thoughtcrime.securesms.backup.BackupProtos.Attachment -import org.thoughtcrime.securesms.backup.BackupProtos.Avatar -import org.thoughtcrime.securesms.backup.BackupProtos.BackupFrame -import org.thoughtcrime.securesms.backup.BackupProtos.DatabaseVersion -import org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference -import org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement -import org.thoughtcrime.securesms.crypto.AttachmentSecret -import org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream -import org.thoughtcrime.securesms.database.AttachmentDatabase -import org.thoughtcrime.securesms.database.GroupReceiptDatabase -import org.thoughtcrime.securesms.database.MmsDatabase -import org.thoughtcrime.securesms.database.MmsSmsColumns -import org.thoughtcrime.securesms.database.SearchDatabase -import org.thoughtcrime.securesms.database.ThreadDatabase -import org.thoughtcrime.securesms.dependencies.DatabaseComponent -import org.thoughtcrime.securesms.util.BackupUtil -import java.io.Closeable -import java.io.File -import java.io.FileOutputStream -import java.io.IOException -import java.io.InputStream -import java.io.OutputStream -import java.security.InvalidAlgorithmParameterException -import java.security.InvalidKeyException -import java.security.MessageDigest -import java.security.NoSuchAlgorithmException -import java.util.LinkedList -import java.util.Locale -import javax.crypto.BadPaddingException -import javax.crypto.Cipher -import javax.crypto.IllegalBlockSizeException -import javax.crypto.Mac -import javax.crypto.NoSuchPaddingException -import javax.crypto.spec.IvParameterSpec -import javax.crypto.spec.SecretKeySpec - -object FullBackupImporter { - /** - * Because BackupProtos.SharedPreference was made only to serialize string values, - * we use these 3-char prefixes to explicitly cast the values before inserting to a preference file. - */ - const val PREF_PREFIX_TYPE_INT = "i__" - const val PREF_PREFIX_TYPE_BOOLEAN = "b__" - - private val TAG = FullBackupImporter::class.java.simpleName - - @JvmStatic - @WorkerThread - @Throws(IOException::class) - fun importFromUri(context: Context, - attachmentSecret: AttachmentSecret, - db: SQLiteDatabase, - fileUri: Uri, - passphrase: String) { - - val baseInputStream = context.contentResolver.openInputStream(fileUri) - ?: throw IOException("Cannot open an input stream for the file URI: $fileUri") - - var count = 0 - try { - BackupRecordInputStream(baseInputStream, passphrase).use { inputStream -> - db.beginTransaction() - dropAllTables(db) - var frame: BackupFrame - while (!inputStream.readFrame().also { frame = it }.end) { - if (count++ % 100 == 0) EventBus.getDefault().post(BackupEvent.createProgress(count)) - when { - frame.hasVersion() -> processVersion(db, frame.version) - frame.hasStatement() -> processStatement(db, frame.statement) - frame.hasPreference() -> processPreference(context, frame.preference) - frame.hasAttachment() -> processAttachment(context, attachmentSecret, db, frame.attachment, inputStream) - frame.hasAvatar() -> processAvatar(context, frame.avatar, inputStream) - } - } - trimEntriesForExpiredMessages(context, db) - db.setTransactionSuccessful() - } - } finally { - if (db.inTransaction()) { - db.endTransaction() - } - } - EventBus.getDefault().post(BackupEvent.createFinished()) - } - - @Throws(IOException::class) - private fun processVersion(db: SQLiteDatabase, version: DatabaseVersion) { - if (version.version > db.version) { - throw DatabaseDowngradeException(db.version, version.version) - } - db.version = version.version - } - - private fun processStatement(db: SQLiteDatabase, statement: SqlStatement) { - val isForSmsFtsSecretTable = statement.statement.contains(SearchDatabase.SMS_FTS_TABLE_NAME + "_") - val isForMmsFtsSecretTable = statement.statement.contains(SearchDatabase.MMS_FTS_TABLE_NAME + "_") - val isForSqliteSecretTable = statement.statement.toLowerCase(Locale.ENGLISH).startsWith("create table sqlite_") - if (isForSmsFtsSecretTable || isForMmsFtsSecretTable || isForSqliteSecretTable) { - Log.i(TAG, "Ignoring import for statement: " + statement.statement) - return - } - val parameters: MutableList = LinkedList() - for (parameter in statement.parametersList) { - when { - parameter.hasStringParamter() -> parameters.add(parameter.stringParamter) - parameter.hasDoubleParameter() -> parameters.add(parameter.doubleParameter) - parameter.hasIntegerParameter() -> parameters.add(parameter.integerParameter) - parameter.hasBlobParameter() -> parameters.add(parameter.blobParameter.toByteArray()) - parameter.hasNullparameter() -> parameters.add(null) - } - } - if (parameters.size > 0) { - db.execSQL(statement.statement, parameters.toTypedArray()) - } else { - db.execSQL(statement.statement) - } - } - - @Throws(IOException::class) - private fun processAttachment(context: Context, attachmentSecret: AttachmentSecret, - db: SQLiteDatabase, attachment: Attachment, - inputStream: BackupRecordInputStream) { - val partsDirectory = context.getDir(AttachmentDatabase.DIRECTORY, Context.MODE_PRIVATE) - val dataFile = File.createTempFile("part", ".mms", partsDirectory) - val output = ModernEncryptingPartOutputStream.createFor(attachmentSecret, dataFile, false) - inputStream.readAttachmentTo(output.second, attachment.length) - val contentValues = ContentValues() - contentValues.put(AttachmentDatabase.DATA, dataFile.absolutePath) - contentValues.put(AttachmentDatabase.THUMBNAIL, null as String?) - contentValues.put(AttachmentDatabase.DATA_RANDOM, output.first) - db.update(AttachmentDatabase.TABLE_NAME, contentValues, - "${AttachmentDatabase.ROW_ID} = ? AND ${AttachmentDatabase.UNIQUE_ID} = ?", - arrayOf(attachment.rowId.toString(), attachment.attachmentId.toString())) - } - - @Throws(IOException::class) - private fun processAvatar(context: Context, avatar: Avatar, inputStream: BackupRecordInputStream) { - inputStream.readAttachmentTo(FileOutputStream( - AvatarHelper.getAvatarFile(context, Address.fromExternal(context, avatar.name))), avatar.length) - } - - @SuppressLint("ApplySharedPref") - private fun processPreference(context: Context, preference: SharedPreference) { - val preferences = context.getSharedPreferences(preference.file, 0) - val key = preference.key - val value = preference.value - - // See the comment next to PREF_PREFIX_TYPE_* constants. - when { - key.startsWith(PREF_PREFIX_TYPE_INT) -> - preferences.edit().putInt( - key.substring(PREF_PREFIX_TYPE_INT.length), - value.toInt() - ).commit() - key.startsWith(PREF_PREFIX_TYPE_BOOLEAN) -> - preferences.edit().putBoolean( - key.substring(PREF_PREFIX_TYPE_BOOLEAN.length), - value.toBoolean() - ).commit() - else -> - preferences.edit().putString(key, value).commit() - } - } - - private fun dropAllTables(db: SQLiteDatabase) { - db.rawQuery("SELECT name, type FROM sqlite_master", null).use { cursor -> - while (cursor != null && cursor.moveToNext()) { - val name = cursor.getString(0) - val type = cursor.getString(1) - if ("table" == type && !name.startsWith("sqlite_")) { - db.execSQL("DROP TABLE IF EXISTS $name") - } - } - } - } - - private fun trimEntriesForExpiredMessages(context: Context, db: SQLiteDatabase) { - val trimmedCondition = " NOT IN (SELECT ${MmsSmsColumns.ID} FROM ${MmsDatabase.TABLE_NAME})" - db.delete(GroupReceiptDatabase.TABLE_NAME, GroupReceiptDatabase.MMS_ID + trimmedCondition, null) - val columns = arrayOf(AttachmentDatabase.ROW_ID, AttachmentDatabase.UNIQUE_ID) - val where = AttachmentDatabase.MMS_ID + trimmedCondition - db.query(AttachmentDatabase.TABLE_NAME, columns, where, null, null, null, null).use { cursor -> - while (cursor != null && cursor.moveToNext()) { - DatabaseComponent.get(context).attachmentDatabase() - .deleteAttachment(AttachmentId(cursor.getLong(0), cursor.getLong(1))) - } - } - db.query(ThreadDatabase.TABLE_NAME, arrayOf(ThreadDatabase.ID), - ThreadDatabase.EXPIRES_IN + " > 0", null, null, null, null).use { cursor -> - while (cursor != null && cursor.moveToNext()) { - DatabaseComponent.get(context).threadDatabase().update(cursor.getLong(0), false) - } - } - } - - private class BackupRecordInputStream : Closeable { - private val inputStream: InputStream - private val cipher: Cipher - private val mac: Mac - private val cipherKey: ByteArray - private val macKey: ByteArray - private val iv: ByteArray - - private var counter = 0 - - @Throws(IOException::class) - constructor(inputStream: InputStream, passphrase: String) : super() { - try { - this.inputStream = inputStream - val headerLengthBytes = ByteArray(4) - Util.readFully(this.inputStream, headerLengthBytes) - val headerLength = Conversions.byteArrayToInt(headerLengthBytes) - val headerFrame = ByteArray(headerLength) - Util.readFully(this.inputStream, headerFrame) - val frame = BackupFrame.parseFrom(headerFrame) - if (!frame.hasHeader()) { - throw IOException("Backup stream does not start with header!") - } - val header = frame.header - iv = header.iv.toByteArray() - if (iv.size != 16) { - throw IOException("Invalid IV length!") - } - val key = BackupUtil.computeBackupKey(passphrase, if (header.hasSalt()) header.salt.toByteArray() else null) - val derived = HKDFv3().deriveSecrets(key, "Backup Export".toByteArray(), 64) - val split = ByteUtil.split(derived, 32, 32) - cipherKey = split[0] - macKey = split[1] - cipher = Cipher.getInstance("AES/CTR/NoPadding") - mac = Mac.getInstance("HmacSHA256") - mac.init(SecretKeySpec(macKey, "HmacSHA256")) - counter = Conversions.byteArrayToInt(iv) - } catch (e: Exception) { - when (e) { - is NoSuchAlgorithmException, - is NoSuchPaddingException, - is InvalidKeyException -> { - throw AssertionError(e) - } - else -> throw e - } - } - } - - @Throws(IOException::class) - fun readFrame(): BackupFrame { - return readFrame(inputStream) - } - - @Throws(IOException::class) - fun readAttachmentTo(out: OutputStream, length: Int) { - var length = length - try { - Conversions.intToByteArray(iv, 0, counter++) - cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(cipherKey, "AES"), IvParameterSpec(iv)) - mac.update(iv) - val buffer = ByteArray(8192) - while (length > 0) { - val read = inputStream.read(buffer, 0, Math.min(buffer.size, length)) - if (read == -1) throw IOException("File ended early!") - mac.update(buffer, 0, read) - val plaintext = cipher.update(buffer, 0, read) - if (plaintext != null) { - out.write(plaintext, 0, plaintext.size) - } - length -= read - } - val plaintext = cipher.doFinal() - if (plaintext != null) { - out.write(plaintext, 0, plaintext.size) - } - out.close() - val ourMac = ByteUtil.trim(mac.doFinal(), 10) - val theirMac = ByteArray(10) - try { - Util.readFully(inputStream, theirMac) - } catch (e: IOException) { - throw IOException(e) - } - if (!MessageDigest.isEqual(ourMac, theirMac)) { - throw IOException("Bad MAC") - } - } catch (e: Exception) { - when (e) { - is InvalidKeyException, - is InvalidAlgorithmParameterException, - is IllegalBlockSizeException, - is BadPaddingException -> { - throw AssertionError(e) - } - else -> throw e - } - } - } - - @Throws(IOException::class) - private fun readFrame(`in`: InputStream?): BackupFrame { - return try { - val length = ByteArray(4) - Util.readFully(`in`, length) - val frame = ByteArray(Conversions.byteArrayToInt(length)) - Util.readFully(`in`, frame) - val theirMac = ByteArray(10) - System.arraycopy(frame, frame.size - 10, theirMac, 0, theirMac.size) - mac.update(frame, 0, frame.size - 10) - val ourMac = ByteUtil.trim(mac.doFinal(), 10) - if (!MessageDigest.isEqual(ourMac, theirMac)) { - throw IOException("Bad MAC") - } - Conversions.intToByteArray(iv, 0, counter++) - cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(cipherKey, "AES"), IvParameterSpec(iv)) - val plaintext = cipher.doFinal(frame, 0, frame.size - 10) - BackupFrame.parseFrom(plaintext) - } catch (e: Exception) { - when (e) { - is InvalidKeyException, - is InvalidAlgorithmParameterException, - is IllegalBlockSizeException, - is BadPaddingException -> { - throw AssertionError(e) - } - else -> throw e - } - } - } - - @Throws(IOException::class) - override fun close() { - inputStream.close() - } - } - - class DatabaseDowngradeException internal constructor(currentVersion: Int, backupVersion: Int) : - IOException("Tried to import a backup with version $backupVersion into a database with version $currentVersion") -} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/LabeledSeparatorView.kt b/app/src/main/java/org/thoughtcrime/securesms/components/LabeledSeparatorView.kt deleted file mode 100644 index df36719db2..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/components/LabeledSeparatorView.kt +++ /dev/null @@ -1,70 +0,0 @@ -package org.thoughtcrime.securesms.components - -import android.content.Context -import android.graphics.Canvas -import android.graphics.Paint -import android.graphics.Path -import android.util.AttributeSet -import android.view.LayoutInflater -import android.widget.RelativeLayout -import network.loki.messenger.R -import network.loki.messenger.databinding.ViewSeparatorBinding -import org.thoughtcrime.securesms.util.toPx -import org.session.libsession.utilities.ThemeUtil - -class LabeledSeparatorView : RelativeLayout { - - private lateinit var binding: ViewSeparatorBinding - private val path = Path() - - private val paint: Paint by lazy { - val result = Paint() - result.style = Paint.Style.STROKE - result.color = ThemeUtil.getThemedColor(context, R.attr.dividerHorizontal) - result.strokeWidth = toPx(1, resources).toFloat() - result.isAntiAlias = true - result - } - - // region Lifecycle - constructor(context: Context) : super(context) { - setUpViewHierarchy() - } - - constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { - setUpViewHierarchy() - } - - constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { - setUpViewHierarchy() - } - - constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) { - setUpViewHierarchy() - } - - private fun setUpViewHierarchy() { - binding = ViewSeparatorBinding.inflate(LayoutInflater.from(context)) - val layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) - addView(binding.root, layoutParams) - setWillNotDraw(false) - } - // endregion - - // region Updating - override fun onDraw(c: Canvas) { - super.onDraw(c) - val w = width.toFloat() - val h = height.toFloat() - val hMargin = toPx(16, resources).toFloat() - path.reset() - path.moveTo(0.0f, h / 2) - path.lineTo(binding.titleTextView.left - hMargin, h / 2) - path.addRoundRect(binding.titleTextView.left - hMargin, toPx(1, resources).toFloat(), binding.titleTextView.right + hMargin, h - toPx(1, resources).toFloat(), h / 2, h / 2, Path.Direction.CCW) - path.moveTo(binding.titleTextView.right + hMargin, h / 2) - path.lineTo(w, h / 2) - path.close() - c.drawPath(path, paint) - } - // endregion -} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/SafeViewPager.kt b/app/src/main/java/org/thoughtcrime/securesms/components/SafeViewPager.kt new file mode 100644 index 0000000000..6748478736 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/components/SafeViewPager.kt @@ -0,0 +1,30 @@ +package org.thoughtcrime.securesms.components + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.view.MotionEvent +import androidx.viewpager.widget.ViewPager + +/** + * An extension of ViewPager to swallow erroneous multi-touch exceptions. + * + * @see https://stackoverflow.com/questions/6919292/pointerindex-out-of-range-android-multitouch + */ +class SafeViewPager @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null +) : ViewPager(context, attrs) { + @SuppressLint("ClickableViewAccessibility") + override fun onTouchEvent(event: MotionEvent?): Boolean = try { + super.onTouchEvent(event) + } catch (e: IllegalArgumentException) { + false + } + + override fun onInterceptTouchEvent(event: MotionEvent?): Boolean = try { + super.onInterceptTouchEvent(event) + } catch (e: IllegalArgumentException) { + false + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index b5f1b96fd7..7844ca4c22 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -21,7 +21,6 @@ import android.widget.Toast import androidx.activity.viewModels import androidx.annotation.DimenRes import androidx.appcompat.app.AlertDialog -import androidx.core.view.drawToBitmap import androidx.core.view.isVisible import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider @@ -210,11 +209,10 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe val searchViewModel: SearchViewModel by viewModels() var searchViewItem: MenuItem? = null + private var emojiPickerVisible = false + private val isScrolledToBottom: Boolean - get() { - val position = layoutManager?.findFirstCompletelyVisibleItemPosition() ?: 0 - return position == 0 - } + get() = binding?.conversationRecyclerView?.isScrolledToBottom ?: true private val layoutManager: LinearLayoutManager? get() { return binding?.conversationRecyclerView?.layoutManager as LinearLayoutManager? } @@ -344,6 +342,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe updateSubtitle() setUpBlockedBanner() binding!!.searchBottomBar.setEventListener(this) + updateSendAfterApprovalText() showOrHideInputIfNeeded() setUpMessageRequestsBar() @@ -443,17 +442,22 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe handleRecyclerViewScrolled() } }) + + binding!!.conversationRecyclerView.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> + showScrollToBottomButtonIfApplicable() + } } // called from onCreate private fun setUpToolBar() { - setSupportActionBar(binding?.toolbar) + val binding = binding ?: return + setSupportActionBar(binding.toolbar) val actionBar = supportActionBar ?: return val recipient = viewModel.recipient ?: return actionBar.title = "" actionBar.setDisplayHomeAsUpEnabled(true) actionBar.setHomeButtonEnabled(true) - binding!!.toolbarContent.conversationTitleView.text = when { + binding.toolbarContent.conversationTitleView.text = when { recipient.isLocalNumber -> getString(R.string.note_to_self) else -> recipient.toShortString() } @@ -463,13 +467,11 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe R.dimen.small_profile_picture_size } val size = resources.getDimension(sizeID).roundToInt() - binding!!.toolbarContent.profilePictureView.root.layoutParams = LinearLayout.LayoutParams(size, size) - binding!!.toolbarContent.profilePictureView.root.glide = glide + binding.toolbarContent.profilePictureView.root.layoutParams = LinearLayout.LayoutParams(size, size) + binding.toolbarContent.profilePictureView.root.glide = glide MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded(viewModel.threadId, this) - val profilePictureView = binding!!.toolbarContent.profilePictureView.root - viewModel.recipient?.let { recipient -> - profilePictureView.update(recipient) - } + val profilePictureView = binding.toolbarContent.profilePictureView.root + viewModel.recipient?.let(profilePictureView::update) } // called from onCreate @@ -574,7 +576,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe val name = contact?.displayName(Contact.ContactContext.REGULAR) ?: sessionID binding?.blockedBannerTextView?.text = resources.getString(R.string.activity_conversation_blocked_banner_text, name) binding?.blockedBanner?.isVisible = recipient.isBlocked - binding?.blockedBanner?.setOnClickListener { viewModel.unblock() } + binding?.blockedBanner?.setOnClickListener { viewModel.unblock(this@ConversationActivityV2) } } private fun setUpLinkPreviewObserver() { @@ -653,7 +655,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe setUpMessageRequestsBar() invalidateOptionsMenu() updateSubtitle() + updateSendAfterApprovalText() showOrHideInputIfNeeded() + binding?.toolbarContent?.profilePictureView?.root?.update(threadRecipient) binding?.toolbarContent?.conversationTitleView?.text = when { threadRecipient.isLocalNumber -> getString(R.string.note_to_self) @@ -662,6 +666,10 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe } } + private fun updateSendAfterApprovalText() { + binding?.textSendAfterApproval?.isVisible = viewModel.showSendAfterApprovalText + } + private fun showOrHideInputIfNeeded() { val recipient = viewModel.recipient if (recipient != null && recipient.isClosedGroupRecipient) { @@ -900,15 +908,14 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe val binding = binding ?: return val wasTypingIndicatorVisibleBefore = binding.typingIndicatorViewContainer.isVisible binding.typingIndicatorViewContainer.isVisible = wasTypingIndicatorVisibleBefore && isScrolledToBottom - binding.typingIndicatorViewContainer.isVisible - showOrHidScrollToBottomButton() + showScrollToBottomButtonIfApplicable() val firstVisiblePosition = layoutManager?.findFirstVisibleItemPosition() ?: -1 unreadCount = min(unreadCount, firstVisiblePosition).coerceAtLeast(0) updateUnreadCountIndicator() } - private fun showOrHidScrollToBottomButton(show: Boolean = true) { - binding?.scrollToBottomButton?.isVisible = show && !isScrolledToBottom && adapter.itemCount > 0 + private fun showScrollToBottomButtonIfApplicable() { + binding?.scrollToBottomButton?.isVisible = !emojiPickerVisible && !isScrolledToBottom && adapter.itemCount > 0 } private fun updateUnreadCountIndicator() { @@ -965,7 +972,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe .setMessage(message) .setNegativeButton(android.R.string.cancel, null) .setPositiveButton(R.string.RecipientPreferenceActivity_block) { _, _ -> - viewModel.block() + viewModel.block(this@ConversationActivityV2) if (deleteThread) { viewModel.deleteThread() finish() @@ -1019,7 +1026,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe .setMessage(message) .setNegativeButton(android.R.string.cancel, null) .setPositiveButton(R.string.ConversationActivity_unblock) { _, _ -> - viewModel.unblock() + viewModel.unblock(this@ConversationActivityV2) }.show() } @@ -1080,33 +1087,37 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe Log.e("Loki", "Failed to show emoji picker", e) return } + + val binding = binding ?: return + + emojiPickerVisible = true ViewUtil.hideKeyboard(this, visibleMessageView) - binding?.reactionsShade?.isVisible = true - showOrHidScrollToBottomButton(false) - binding?.conversationRecyclerView?.suppressLayout(true) + binding.reactionsShade.isVisible = true + binding.scrollToBottomButton.isVisible = false + binding.conversationRecyclerView.suppressLayout(true) reactionDelegate.setOnActionSelectedListener(ReactionsToolbarListener(message)) reactionDelegate.setOnHideListener(object: ConversationReactionOverlay.OnHideListener { override fun startHide() { - binding?.reactionsShade?.let { + emojiPickerVisible = false + binding.reactionsShade.let { ViewUtil.fadeOut(it, resources.getInteger(R.integer.reaction_scrubber_hide_duration), View.GONE) } - showOrHidScrollToBottomButton(true) + showScrollToBottomButtonIfApplicable() } override fun onHide() { - binding?.conversationRecyclerView?.suppressLayout(false) + binding.conversationRecyclerView.suppressLayout(false) WindowUtil.setLightStatusBarFromTheme(this@ConversationActivityV2); WindowUtil.setLightNavigationBarFromTheme(this@ConversationActivityV2); } }) - val contentBounds = Rect() - visibleMessageView.messageContentView.getGlobalVisibleRect(contentBounds) + val topLeft = intArrayOf(0, 0).also { visibleMessageView.messageContentView.getLocationInWindow(it) } val selectedConversationModel = SelectedConversationModel( messageContentBitmap, - contentBounds.left.toFloat(), - contentBounds.top.toFloat(), + topLeft[0].toFloat(), + topLeft[1].toFloat(), visibleMessageView.messageContentView.width, message.isOutgoing, visibleMessageView.messageContentView @@ -1356,7 +1367,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe override fun sendMessage() { val recipient = viewModel.recipient ?: return if (recipient.isContactRecipient && recipient.isBlocked) { - BlockedDialog(recipient).show(supportFragmentManager, "Blocked Dialog") + BlockedDialog(recipient, this).show(supportFragmentManager, "Blocked Dialog") return } val binding = binding ?: return @@ -1747,6 +1758,13 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe endActionMode() } + override fun resyncMessage(messages: Set) { + messages.iterator().forEach { messageRecord -> + ResendMessageUtilities.resend(this, messageRecord, viewModel.blindedPublicKey, isResync = true) + } + endActionMode() + } + override fun resendMessage(messages: Set) { messages.iterator().forEach { messageRecord -> ResendMessageUtilities.resend(this, messageRecord, viewModel.blindedPublicKey) @@ -1907,6 +1925,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe val selectedItems = setOf(message) when (action) { ConversationReactionOverlay.Action.REPLY -> reply(selectedItems) + ConversationReactionOverlay.Action.RESYNC -> resyncMessage(selectedItems) ConversationReactionOverlay.Action.RESEND -> resendMessage(selectedItems) ConversationReactionOverlay.Action.DOWNLOAD -> saveAttachment(selectedItems) ConversationReactionOverlay.Action.COPY_MESSAGE -> copyMessages(selectedItems) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java index b3c151690f..20462bef34 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationReactionOverlay.java @@ -81,6 +81,8 @@ public final class ConversationReactionOverlay extends FrameLayout { private View dropdownAnchor; private LinearLayout conversationItem; + private View conversationBubble; + private TextView conversationTimestamp; private View backgroundView; private ConstraintLayout foregroundView; private EmojiImageView[] emojiViews; @@ -116,6 +118,8 @@ public final class ConversationReactionOverlay extends FrameLayout { dropdownAnchor = findViewById(R.id.dropdown_anchor); conversationItem = findViewById(R.id.conversation_item); + conversationBubble = conversationItem.findViewById(R.id.conversation_item_bubble); + conversationTimestamp = conversationItem.findViewById(R.id.conversation_item_timestamp); backgroundView = findViewById(R.id.conversation_reaction_scrubber_background); foregroundView = findViewById(R.id.conversation_reaction_scrubber_foreground); @@ -165,10 +169,8 @@ public final class ConversationReactionOverlay extends FrameLayout { Bitmap conversationItemSnapshot = selectedConversationModel.getBitmap(); - View conversationBubble = conversationItem.findViewById(R.id.conversation_item_bubble); conversationBubble.setLayoutParams(new LinearLayout.LayoutParams(conversationItemSnapshot.getWidth(), conversationItemSnapshot.getHeight())); conversationBubble.setBackground(new BitmapDrawable(getResources(), conversationItemSnapshot)); - TextView conversationTimestamp = conversationItem.findViewById(R.id.conversation_item_timestamp); conversationTimestamp.setText(DateUtils.getDisplayFormattedTimeSpanString(getContext(), Locale.getDefault(), messageRecord.getTimestamp())); updateConversationTimestamp(messageRecord); @@ -190,12 +192,8 @@ public final class ConversationReactionOverlay extends FrameLayout { } private void updateConversationTimestamp(MessageRecord message) { - View bubble = conversationItem.findViewById(R.id.conversation_item_bubble); - View timestamp = conversationItem.findViewById(R.id.conversation_item_timestamp); - conversationItem.removeAllViewsInLayout(); - conversationItem.addView(message.isOutgoing() ? timestamp : bubble); - conversationItem.addView(message.isOutgoing() ? bubble : timestamp); - conversationItem.requestLayout(); + if (message.isOutgoing()) conversationBubble.bringToFront(); + else conversationTimestamp.bringToFront(); } private void showAfterLayout(@NonNull MessageRecord messageRecord, @@ -203,10 +201,11 @@ public final class ConversationReactionOverlay extends FrameLayout { boolean isMessageOnLeft) { contextMenu = new ConversationContextMenu(dropdownAnchor, getMenuActionItems(messageRecord)); - float itemX = isMessageOnLeft ? scrubberHorizontalMargin : + float endX = isMessageOnLeft ? scrubberHorizontalMargin : selectedConversationModel.getBubbleX() - conversationItem.getWidth() + selectedConversationModel.getBubbleWidth(); - conversationItem.setX(itemX); - conversationItem.setY(selectedConversationModel.getBubbleY() - statusBarHeight); + float endY = selectedConversationModel.getBubbleY() - statusBarHeight; + conversationItem.setX(endX); + conversationItem.setY(endY); Bitmap conversationItemSnapshot = selectedConversationModel.getBitmap(); boolean isWideLayout = contextMenu.getMaxWidth() + scrubberWidth < getWidth(); @@ -214,8 +213,6 @@ public final class ConversationReactionOverlay extends FrameLayout { int overlayHeight = getHeight(); int bubbleWidth = selectedConversationModel.getBubbleWidth(); - float endX = itemX; - float endY = conversationItem.getY(); float endApparentTop = endY; float endScale = 1f; @@ -265,9 +262,7 @@ public final class ConversationReactionOverlay extends FrameLayout { } } else { endY = overlayHeight - contextMenu.getMaxHeight() - menuPadding - conversationItemSnapshot.getHeight(); - - float contextMenuTop = endY + conversationItemSnapshot.getHeight(); - reactionBarBackgroundY = getReactionBarOffsetForTouch(selectedConversationModel.getBubbleY(), contextMenuTop, menuPadding, reactionBarOffset, reactionBarHeight, reactionBarTopPadding, endY); + reactionBarBackgroundY = endY - reactionBarHeight - menuPadding; } endApparentTop = endY; @@ -354,11 +349,14 @@ public final class ConversationReactionOverlay extends FrameLayout { int revealDuration = getContext().getResources().getInteger(R.integer.reaction_scrubber_reveal_duration); + conversationBubble.animate() + .scaleX(endScale) + .scaleY(endScale) + .setDuration(revealDuration); + conversationItem.animate() .x(endX) .y(endY) - .scaleX(endScale) - .scaleY(endScale) .setDuration(revealDuration); } @@ -663,7 +661,8 @@ public final class ConversationReactionOverlay extends FrameLayout { items.add(new ActionItem(R.attr.menu_select_icon, getContext().getResources().getString(R.string.conversation_context__menu_select), () -> handleActionItemClicked(Action.SELECT), getContext().getResources().getString(R.string.AccessibilityId_select))); // Reply - if (!message.isPending() && !message.isFailed()) { + boolean canWrite = openGroup == null || openGroup.getCanWrite(); + if (canWrite && !message.isPending() && !message.isFailed()) { items.add( new ActionItem(R.attr.menu_reply_icon, getContext().getResources().getString(R.string.conversation_context__menu_reply), () -> handleActionItemClicked(Action.REPLY), getContext().getResources().getString(R.string.AccessibilityId_reply_message)) @@ -703,6 +702,10 @@ public final class ConversationReactionOverlay extends FrameLayout { if (message.isFailed()) { items.add(new ActionItem(R.attr.menu_reply_icon, getContext().getResources().getString(R.string.conversation_context__menu_resend_message), () -> handleActionItemClicked(Action.RESEND))); } + // Resync + if (message.isSyncFailed()) { + items.add(new ActionItem(R.attr.menu_reply_icon, getContext().getResources().getString(R.string.conversation_context__menu_resync_message), () -> handleActionItemClicked(Action.RESYNC))); + } // Save media if (message.isMms() && ((MediaMmsMessageRecord)message).containsMediaSlide()) { items.add(new ActionItem(R.attr.menu_save_icon, getContext().getResources().getString(R.string.conversation_context_image__save_attachment), () -> handleActionItemClicked(Action.DOWNLOAD), @@ -888,6 +891,7 @@ public final class ConversationReactionOverlay extends FrameLayout { public enum Action { REPLY, RESEND, + RESYNC, DOWNLOAD, COPY_MESSAGE, COPY_SESSION_ID, diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt index 7f6768ee93..b8b460b603 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt @@ -1,7 +1,9 @@ package org.thoughtcrime.securesms.conversation.v2 +import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.lifecycleScope import androidx.lifecycle.viewModelScope import com.goterl.lazysodium.utils.KeyPair import dagger.assisted.Assisted @@ -22,6 +24,7 @@ import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.database.Storage import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.repository.ConversationRepository +import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities import java.util.UUID class ConversationViewModel( @@ -31,6 +34,9 @@ class ConversationViewModel( private val storage: Storage ) : ViewModel() { + val showSendAfterApprovalText: Boolean + get() = recipient?.run { isContactRecipient && !isLocalNumber && !hasApprovedMe() } ?: false + private val _uiState = MutableStateFlow(ConversationUiState()) val uiState: StateFlow = _uiState @@ -75,17 +81,27 @@ class ConversationViewModel( repository.inviteContacts(threadId, contacts) } - fun block() { + fun block(context: Context) { val recipient = recipient ?: return Log.w("Loki", "Recipient was null for block action") if (recipient.isContactRecipient) { repository.setBlocked(recipient, true) + + // TODO: Remove in UserConfig branch + GlobalScope.launch(Dispatchers.IO) { + ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context) + } } } - fun unblock() { + fun unblock(context: Context) { val recipient = recipient ?: return Log.w("Loki", "Recipient was null for unblock action") if (recipient.isContactRecipient) { repository.setBlocked(recipient, false) + + // TODO: Remove in UserConfig branch + GlobalScope.launch(Dispatchers.IO) { + ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context) + } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/DeleteOptionsBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/DeleteOptionsBottomSheet.kt index 66f33cf299..b6212b8542 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/DeleteOptionsBottomSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/DeleteOptionsBottomSheet.kt @@ -69,7 +69,6 @@ class DeleteOptionsBottomSheet : BottomSheetDialogFragment(), View.OnClickListen override fun onStart() { super.onStart() val window = dialog?.window ?: return - val isLightMode = UiModeUtilities.isDayUiMode(requireContext()) - window.setDimAmount(if (isLightMode) 0.1f else 0.75f) + window.setDimAmount(0.6f) } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ModalUrlBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ModalUrlBottomSheet.kt index 28c86b3311..54deea1c8d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ModalUrlBottomSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ModalUrlBottomSheet.kt @@ -60,8 +60,7 @@ class ModalUrlBottomSheet(private val url: String): BottomSheetDialogFragment(), override fun onStart() { super.onStart() val window = dialog?.window ?: return - val isLightMode = UiModeUtilities.isDayUiMode(requireContext()) - window.setDimAmount(if (isLightMode) 0.1f else 0.75f) + window.setDimAmount(0.6f) } override fun onClick(v: View?) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/WindowUtil.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/WindowUtil.java index 4bff4e76aa..6083bb267c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/WindowUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/WindowUtil.java @@ -38,14 +38,10 @@ public final class WindowUtil { } public static void setNavigationBarColor(@NonNull Window window, @ColorInt int color) { - if (Build.VERSION.SDK_INT < 21) return; - window.setNavigationBarColor(color); } public static void setLightStatusBarFromTheme(@NonNull Activity activity) { - if (Build.VERSION.SDK_INT < 23) return; - final boolean isLightStatusBar = ThemeUtil.getThemedBoolean(activity, android.R.attr.windowLightStatusBar); if (isLightStatusBar) setLightStatusBar(activity.getWindow()); @@ -53,20 +49,14 @@ public final class WindowUtil { } public static void clearLightStatusBar(@NonNull Window window) { - if (Build.VERSION.SDK_INT < 23) return; - clearSystemUiFlags(window, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); } public static void setLightStatusBar(@NonNull Window window) { - if (Build.VERSION.SDK_INT < 23) return; - setSystemUiFlags(window, View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); } public static void setStatusBarColor(@NonNull Window window, @ColorInt int color) { - if (Build.VERSION.SDK_INT < 21) return; - window.setStatusBarColor(color); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/dialogs/BlockedDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/dialogs/BlockedDialog.kt index 39ca7c6913..bcabca98f1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/dialogs/BlockedDialog.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/dialogs/BlockedDialog.kt @@ -1,20 +1,25 @@ package org.thoughtcrime.securesms.conversation.v2.dialogs +import android.content.Context import android.graphics.Typeface import android.text.Spannable import android.text.SpannableStringBuilder import android.text.style.StyleSpan import android.view.LayoutInflater import androidx.appcompat.app.AlertDialog +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import network.loki.messenger.R import network.loki.messenger.databinding.DialogBlockedBinding import org.session.libsession.messaging.contacts.Contact import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog import org.thoughtcrime.securesms.dependencies.DatabaseComponent +import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities /** Shown upon sending a message to a user that's blocked. */ -class BlockedDialog(private val recipient: Recipient) : BaseDialog() { +class BlockedDialog(private val recipient: Recipient, private val context: Context) : BaseDialog() { override fun setContentView(builder: AlertDialog.Builder) { val binding = DialogBlockedBinding.inflate(LayoutInflater.from(requireContext())) @@ -37,5 +42,10 @@ class BlockedDialog(private val recipient: Recipient) : BaseDialog() { private fun unblock() { DatabaseComponent.get(requireContext()).recipientDatabase().setBlocked(recipient, false) dismiss() + + // TODO: Remove in UserConfig branch + GlobalScope.launch(Dispatchers.IO) { + ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context) + } } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationActionModeCallback.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationActionModeCallback.kt index d475a64448..f86920f90f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationActionModeCallback.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationActionModeCallback.kt @@ -70,6 +70,8 @@ class ConversationActionModeCallback(private val adapter: ConversationAdapter, p menu.findItem(R.id.menu_message_details).isVisible = (selectedItems.size == 1 && firstMessage.isOutgoing) // Resend menu.findItem(R.id.menu_context_resend).isVisible = (selectedItems.size == 1 && firstMessage.isFailed) + // Resync + menu.findItem(R.id.menu_context_resync).isVisible = (selectedItems.size == 1 && firstMessage.isSyncFailed) // Save media menu.findItem(R.id.menu_context_save_attachment).isVisible = (selectedItems.size == 1 && firstMessage.isMms && (firstMessage as MediaMmsMessageRecord).containsMediaSlide()) @@ -90,6 +92,7 @@ class ConversationActionModeCallback(private val adapter: ConversationAdapter, p R.id.menu_context_ban_and_delete_all -> delegate?.banAndDeleteAll(selectedItems) R.id.menu_context_copy -> delegate?.copyMessages(selectedItems) R.id.menu_context_copy_public_key -> delegate?.copySessionID(selectedItems) + R.id.menu_context_resync -> delegate?.resyncMessage(selectedItems) R.id.menu_context_resend -> delegate?.resendMessage(selectedItems) R.id.menu_message_details -> delegate?.showMessageDetail(selectedItems) R.id.menu_context_save_attachment -> delegate?.saveAttachment(selectedItems) @@ -113,6 +116,7 @@ interface ConversationActionModeCallbackDelegate { fun banAndDeleteAll(messages: Set) fun copyMessages(messages: Set) fun copySessionID(messages: Set) + fun resyncMessage(messages: Set) fun resendMessage(messages: Set) fun showMessageDetail(messages: Set) fun saveAttachment(messages: Set) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt index 2c04bcfce3..319140731a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt @@ -292,50 +292,55 @@ class VisibleMessageView : LinearLayout { @StringRes val messageText: Int?, val contentDescription: String?) - private fun getMessageStatusImage(message: MessageRecord): MessageStatusInfo { - return when { - !message.isOutgoing -> MessageStatusInfo(null, - null, - null, - null) - message.isFailed -> - MessageStatusInfo( - R.drawable.ic_delivery_status_failed, - resources.getColor(R.color.destructive, context.theme), - R.string.delivery_status_failed, - null - ) - message.isPending -> - MessageStatusInfo( - R.drawable.ic_delivery_status_sending, - context.getColorFromAttr(R.attr.message_status_color), R.string.delivery_status_sending, - context.getString(R.string.AccessibilityId_message_sent_status_pending) - ) - message.isRead -> - MessageStatusInfo( - R.drawable.ic_delivery_status_read, - context.getColorFromAttr(R.attr.message_status_color), R.string.delivery_status_read, - null - ) - else -> - MessageStatusInfo( - R.drawable.ic_delivery_status_sent, - context.getColorFromAttr(R.attr.message_status_color), - R.string.delivery_status_sent, - context.getString(R.string.AccessibilityId_message_sent_status_tick) - ) - } + private fun getMessageStatusImage(message: MessageRecord): MessageStatusInfo = when { + message.isFailed -> + MessageStatusInfo( + R.drawable.ic_delivery_status_failed, + resources.getColor(R.color.destructive, context.theme), + R.string.delivery_status_failed, + null + ) + message.isSyncFailed -> + MessageStatusInfo( + R.drawable.ic_delivery_status_failed, + context.getColor(R.color.accent_orange), + R.string.delivery_status_sync_failed, + null + ) + message.isPending -> + MessageStatusInfo( + R.drawable.ic_delivery_status_sending, + context.getColorFromAttr(R.attr.message_status_color), R.string.delivery_status_sending, + context.getString(R.string.AccessibilityId_message_sent_status_pending) + ) + message.isResyncing -> + MessageStatusInfo( + R.drawable.ic_delivery_status_sending, + context.getColor(R.color.accent_orange), R.string.delivery_status_syncing, + context.getString(R.string.AccessibilityId_message_sent_status_syncing) + ) + message.isRead -> + MessageStatusInfo( + R.drawable.ic_delivery_status_read, + context.getColorFromAttr(R.attr.message_status_color), R.string.delivery_status_read, + null + ) + else -> + MessageStatusInfo( + R.drawable.ic_delivery_status_sent, + context.getColorFromAttr(R.attr.message_status_color), + R.string.delivery_status_sent, + context.getString(R.string.AccessibilityId_message_sent_status_tick) + ) } private fun updateExpirationTimer(message: MessageRecord) { val container = binding.messageInnerContainer val content = binding.messageContentView.root val expiration = binding.expirationTimerView - val spacing = binding.messageContentSpacing container.removeAllViewsInLayout() container.addView(if (message.isOutgoing) expiration else content) container.addView(if (message.isOutgoing) content else expiration) - container.addView(spacing, if (message.isOutgoing) 0 else 2) val containerParams = container.layoutParams as ConstraintLayout.LayoutParams containerParams.horizontalBias = if (message.isOutgoing) 1f else 0f container.layoutParams = containerParams diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/BaseDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/BaseDialog.kt index e1456a7f94..c3a9689a00 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/BaseDialog.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/BaseDialog.kt @@ -14,9 +14,7 @@ open class BaseDialog : DialogFragment() { val builder = AlertDialog.Builder(requireContext()) setContentView(builder) val result = builder.create() - result.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - val isLightMode = UiModeUtilities.isDayUiMode(requireContext()) - result.window?.setDimAmount(if (isLightMode) 0.1f else 0.75f) + result.window?.setDimAmount(0.6f) return result } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt index 80f4cc0bf8..e01a75b30c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.conversation.v2.utilities import android.content.Context import org.session.libsession.messaging.MessagingModuleConfiguration +import org.session.libsession.messaging.messages.Destination import org.session.libsession.messaging.messages.visible.LinkPreview import org.session.libsession.messaging.messages.visible.OpenGroupInvitation import org.session.libsession.messaging.messages.visible.Quote @@ -15,7 +16,7 @@ import org.thoughtcrime.securesms.database.model.MmsMessageRecord object ResendMessageUtilities { - fun resend(context: Context, messageRecord: MessageRecord, userBlindedKey: String?) { + fun resend(context: Context, messageRecord: MessageRecord, userBlindedKey: String?, isResync: Boolean = false) { val recipient: Recipient = messageRecord.recipient val message = VisibleMessage() message.id = messageRecord.getId() @@ -55,8 +56,13 @@ object ResendMessageUtilities { val sentTimestamp = message.sentTimestamp val sender = MessagingModuleConfiguration.shared.storage.getUserPublicKey() if (sentTimestamp != null && sender != null) { - MessagingModuleConfiguration.shared.storage.markAsSending(sentTimestamp, sender) + if (isResync) { + MessagingModuleConfiguration.shared.storage.markAsResyncing(sentTimestamp, sender) + MessageSender.send(message, Destination.from(recipient.address), isSyncMessage = true) + } else { + MessagingModuleConfiguration.shared.storage.markAsSending(sentTimestamp, sender) + MessageSender.send(message, recipient.address) + } } - MessageSender.send(message, recipient.address) } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt index 800ace54c3..7a47b92756 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/TextUtilities.kt @@ -38,13 +38,12 @@ object TextUtilities { fun TextView.getIntersectedModalSpans(hitRect: Rect): List { val textLayout = layout ?: return emptyList() val lineRect = Rect() - val bodyTextRect = Rect() - getGlobalVisibleRect(bodyTextRect) + val offset = intArrayOf(0, 0).also { getLocationOnScreen(it) } val textSpannable = text.toSpannable() return (0 until textLayout.lineCount).flatMap { line -> textLayout.getLineBounds(line, lineRect) - lineRect.offset(bodyTextRect.left + totalPaddingLeft, bodyTextRect.top + totalPaddingTop) - if ((Rect(lineRect)).contains(hitRect)) { + lineRect.offset(offset[0] + totalPaddingLeft, offset[1] + totalPaddingTop) + if (lineRect.contains(hitRect)) { // calculate the url span intersected with (if any) val off = textLayout.getOffsetForHorizontal(line, hitRect.left.toFloat()) // left and right will be the same textSpannable.getSpans(off, off).toList() diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailView.kt index e9a085dad9..4a9986d6ec 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailView.kt @@ -126,10 +126,9 @@ open class ThumbnailView: FrameLayout { buildThumbnailGlideRequest(glide, slide).into(GlideDrawableListeningTarget(binding.thumbnailImage, binding.thumbnailLoadIndicator, result)) } slide.hasPlaceholder() -> { - buildPlaceholderGlideRequest(glide, slide).into(GlideBitmapListeningTarget(binding.thumbnailImage, binding.thumbnailLoadIndicator, result)) + buildPlaceholderGlideRequest(glide, slide).into(GlideBitmapListeningTarget(binding.thumbnailImage, null, result)) } else -> { - binding.thumbnailLoadIndicator.isVisible = false glide.clear(binding.thumbnailImage) result.set(false) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java index 43e9865598..7f0edddeb0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/KeyStoreHelper.java @@ -1,13 +1,13 @@ package org.thoughtcrime.securesms.crypto; -import android.os.Build; +import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK; + import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.util.Base64; import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonGenerator; @@ -45,44 +45,50 @@ public final class KeyStoreHelper { private static final String ANDROID_KEY_STORE = "AndroidKeyStore"; private static final String KEY_ALIAS = "SignalSecret"; - @RequiresApi(Build.VERSION_CODES.M) public static SealedData seal(@NonNull byte[] input) { SecretKey secretKey = getOrCreateKeyStoreEntry(); try { - Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); - cipher.init(Cipher.ENCRYPT_MODE, secretKey); + // Cipher operations are not thread-safe so we synchronize over them through doFinal to + // prevent crashes with quickly repeated encrypt/decrypt operations + // https://github.com/mozilla-mobile/android-components/issues/5342 + synchronized (CIPHER_LOCK) { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, secretKey); - byte[] iv = cipher.getIV(); - byte[] data = cipher.doFinal(input); + byte[] iv = cipher.getIV(); + byte[] data = cipher.doFinal(input); - return new SealedData(iv, data); + return new SealedData(iv, data); + } } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { throw new AssertionError(e); } } - @RequiresApi(Build.VERSION_CODES.M) public static byte[] unseal(@NonNull SealedData sealedData) { SecretKey secretKey = getKeyStoreEntry(); try { - Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); - cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(128, sealedData.iv)); + // Cipher operations are not thread-safe so we synchronize over them through doFinal to + // prevent crashes with quickly repeated encrypt/decrypt operations + // https://github.com/mozilla-mobile/android-components/issues/5342 + synchronized (CIPHER_LOCK) { + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(128, sealedData.iv)); - return cipher.doFinal(sealedData.data); + return cipher.doFinal(sealedData.data); + } } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) { throw new AssertionError(e); } } - @RequiresApi(Build.VERSION_CODES.M) private static SecretKey getOrCreateKeyStoreEntry() { if (hasKeyStoreEntry()) return getKeyStoreEntry(); else return createKeyStoreEntry(); } - @RequiresApi(Build.VERSION_CODES.M) private static SecretKey createKeyStoreEntry() { try { KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE); @@ -99,7 +105,6 @@ public final class KeyStoreHelper { } } - @RequiresApi(Build.VERSION_CODES.M) private static SecretKey getKeyStoreEntry() { KeyStore keyStore = getKeyStore(); @@ -137,7 +142,6 @@ public final class KeyStoreHelper { } } - @RequiresApi(Build.VERSION_CODES.M) private static boolean hasKeyStoreEntry() { try { KeyStore ks = KeyStore.getInstance(ANDROID_KEY_STORE); @@ -202,7 +206,5 @@ public final class KeyStoreHelper { return Base64.decode(p.getValueAsString(), Base64.NO_WRAP | Base64.NO_PADDING); } } - } - } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java deleted file mode 100644 index ef4746923b..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java +++ /dev/null @@ -1,249 +0,0 @@ -package org.thoughtcrime.securesms.database; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import androidx.annotation.NonNull; - -import net.zetetic.database.sqlcipher.SQLiteDatabase; - -import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; -import org.thoughtcrime.securesms.jobmanager.persistence.ConstraintSpec; -import org.thoughtcrime.securesms.jobmanager.persistence.DependencySpec; -import org.thoughtcrime.securesms.jobmanager.persistence.FullSpec; -import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec; - -import java.util.LinkedList; -import java.util.List; - -public class JobDatabase extends Database { - - public static final String[] CREATE_TABLE = new String[] { Jobs.CREATE_TABLE, - Constraints.CREATE_TABLE, - Dependencies.CREATE_TABLE }; - - public static final class Jobs { - public static final String TABLE_NAME = "job_spec"; - private static final String ID = "_id"; - private static final String JOB_SPEC_ID = "job_spec_id"; - private static final String FACTORY_KEY = "factory_key"; - private static final String QUEUE_KEY = "queue_key"; - private static final String CREATE_TIME = "create_time"; - private static final String NEXT_RUN_ATTEMPT_TIME = "next_run_attempt_time"; - private static final String RUN_ATTEMPT = "run_attempt"; - private static final String MAX_ATTEMPTS = "max_attempts"; - private static final String MAX_BACKOFF = "max_backoff"; - private static final String MAX_INSTANCES = "max_instances"; - private static final String LIFESPAN = "lifespan"; - private static final String SERIALIZED_DATA = "serialized_data"; - private static final String IS_RUNNING = "is_running"; - - private static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + - JOB_SPEC_ID + " TEXT UNIQUE, " + - FACTORY_KEY + " TEXT, " + - QUEUE_KEY + " TEXT, " + - CREATE_TIME + " INTEGER, " + - NEXT_RUN_ATTEMPT_TIME + " INTEGER, " + - RUN_ATTEMPT + " INTEGER, " + - MAX_ATTEMPTS + " INTEGER, " + - MAX_BACKOFF + " INTEGER, " + - MAX_INSTANCES + " INTEGER, " + - LIFESPAN + " INTEGER, " + - SERIALIZED_DATA + " TEXT, " + - IS_RUNNING + " INTEGER)"; - } - - public static final class Constraints { - public static final String TABLE_NAME = "constraint_spec"; - private static final String ID = "_id"; - private static final String JOB_SPEC_ID = "job_spec_id"; - private static final String FACTORY_KEY = "factory_key"; - - private static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + - JOB_SPEC_ID + " TEXT, " + - FACTORY_KEY + " TEXT, " + - "UNIQUE(" + JOB_SPEC_ID + ", " + FACTORY_KEY + "))"; - } - - public static final class Dependencies { - public static final String TABLE_NAME = "dependency_spec"; - private static final String ID = "_id"; - private static final String JOB_SPEC_ID = "job_spec_id"; - private static final String DEPENDS_ON_JOB_SPEC_ID = "depends_on_job_spec_id"; - - private static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + - JOB_SPEC_ID + " TEXT, " + - DEPENDS_ON_JOB_SPEC_ID + " TEXT, " + - "UNIQUE(" + JOB_SPEC_ID + ", " + DEPENDS_ON_JOB_SPEC_ID + "))"; - } - - - public JobDatabase(Context context, SQLCipherOpenHelper databaseHelper) { - super(context, databaseHelper); - } - - public synchronized void insertJobs(@NonNull List fullSpecs) { - SQLiteDatabase db = databaseHelper.getWritableDatabase(); - - db.beginTransaction(); - - try { - for (FullSpec fullSpec : fullSpecs) { - insertJobSpec(db, fullSpec.getJobSpec()); - insertConstraintSpecs(db, fullSpec.getConstraintSpecs()); - insertDependencySpecs(db, fullSpec.getDependencySpecs()); - } - - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - public synchronized @NonNull List getAllJobSpecs() { - List jobs = new LinkedList<>(); - - try (Cursor cursor = databaseHelper.getReadableDatabase().query(Jobs.TABLE_NAME, null, null, null, null, null, Jobs.CREATE_TIME + ", " + Jobs.ID + " ASC")) { - while (cursor != null && cursor.moveToNext()) { - jobs.add(jobSpecFromCursor(cursor)); - } - } - - return jobs; - } - - public synchronized void updateJobRunningState(@NonNull String id, boolean isRunning) { - ContentValues contentValues = new ContentValues(); - contentValues.put(Jobs.IS_RUNNING, isRunning ? 1 : 0); - - String query = Jobs.JOB_SPEC_ID + " = ?"; - String[] args = new String[]{ id }; - - databaseHelper.getWritableDatabase().update(Jobs.TABLE_NAME, contentValues, query, args); - } - - public synchronized void updateJobAfterRetry(@NonNull String id, boolean isRunning, int runAttempt, long nextRunAttemptTime) { - ContentValues contentValues = new ContentValues(); - contentValues.put(Jobs.IS_RUNNING, isRunning ? 1 : 0); - contentValues.put(Jobs.RUN_ATTEMPT, runAttempt); - contentValues.put(Jobs.NEXT_RUN_ATTEMPT_TIME, nextRunAttemptTime); - - String query = Jobs.JOB_SPEC_ID + " = ?"; - String[] args = new String[]{ id }; - - databaseHelper.getWritableDatabase().update(Jobs.TABLE_NAME, contentValues, query, args); - } - - public synchronized void updateAllJobsToBePending() { - ContentValues contentValues = new ContentValues(); - contentValues.put(Jobs.IS_RUNNING, 0); - - databaseHelper.getWritableDatabase().update(Jobs.TABLE_NAME, contentValues, null, null); - } - - public synchronized void deleteJobs(@NonNull List jobIds) { - SQLiteDatabase db = databaseHelper.getWritableDatabase(); - - db.beginTransaction(); - - try { - for (String jobId : jobIds) { - String[] arg = new String[]{jobId}; - - db.delete(Jobs.TABLE_NAME, Jobs.JOB_SPEC_ID + " = ?", arg); - db.delete(Constraints.TABLE_NAME, Constraints.JOB_SPEC_ID + " = ?", arg); - db.delete(Dependencies.TABLE_NAME, Dependencies.JOB_SPEC_ID + " = ?", arg); - db.delete(Dependencies.TABLE_NAME, Dependencies.DEPENDS_ON_JOB_SPEC_ID + " = ?", arg); - } - - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - public synchronized @NonNull List getAllConstraintSpecs() { - List constraints = new LinkedList<>(); - - try (Cursor cursor = databaseHelper.getReadableDatabase().query(Constraints.TABLE_NAME, null, null, null, null, null, null)) { - while (cursor != null && cursor.moveToNext()) { - constraints.add(constraintSpecFromCursor(cursor)); - } - } - - return constraints; - } - - public synchronized @NonNull List getAllDependencySpecs() { - List dependencies = new LinkedList<>(); - - try (Cursor cursor = databaseHelper.getReadableDatabase().query(Dependencies.TABLE_NAME, null, null, null, null, null, null)) { - while (cursor != null && cursor.moveToNext()) { - dependencies.add(dependencySpecFromCursor(cursor)); - } - } - - return dependencies; - } - - private void insertJobSpec(@NonNull SQLiteDatabase db, @NonNull JobSpec job) { - ContentValues contentValues = new ContentValues(); - contentValues.put(Jobs.JOB_SPEC_ID, job.getId()); - contentValues.put(Jobs.FACTORY_KEY, job.getFactoryKey()); - contentValues.put(Jobs.QUEUE_KEY, job.getQueueKey()); - contentValues.put(Jobs.CREATE_TIME, job.getCreateTime()); - contentValues.put(Jobs.NEXT_RUN_ATTEMPT_TIME, job.getNextRunAttemptTime()); - contentValues.put(Jobs.RUN_ATTEMPT, job.getRunAttempt()); - contentValues.put(Jobs.MAX_ATTEMPTS, job.getMaxAttempts()); - contentValues.put(Jobs.MAX_BACKOFF, job.getMaxBackoff()); - contentValues.put(Jobs.MAX_INSTANCES, job.getMaxInstances()); - contentValues.put(Jobs.LIFESPAN, job.getLifespan()); - contentValues.put(Jobs.SERIALIZED_DATA, job.getSerializedData()); - contentValues.put(Jobs.IS_RUNNING, job.isRunning() ? 1 : 0); - - db.insertWithOnConflict(Jobs.TABLE_NAME, null, contentValues, SQLiteDatabase.CONFLICT_IGNORE); - } - - private void insertConstraintSpecs(@NonNull SQLiteDatabase db, @NonNull List constraints) { - for (ConstraintSpec constraintSpec : constraints) { - ContentValues contentValues = new ContentValues(); - contentValues.put(Constraints.JOB_SPEC_ID, constraintSpec.getJobSpecId()); - contentValues.put(Constraints.FACTORY_KEY, constraintSpec.getFactoryKey()); - db.insertWithOnConflict(Constraints.TABLE_NAME, null ,contentValues, SQLiteDatabase.CONFLICT_IGNORE); - } - } - - private void insertDependencySpecs(@NonNull SQLiteDatabase db, @NonNull List dependencies) { - for (DependencySpec dependencySpec : dependencies) { - ContentValues contentValues = new ContentValues(); - contentValues.put(Dependencies.JOB_SPEC_ID, dependencySpec.getJobId()); - contentValues.put(Dependencies.DEPENDS_ON_JOB_SPEC_ID, dependencySpec.getDependsOnJobId()); - db.insertWithOnConflict(Dependencies.TABLE_NAME, null, contentValues, SQLiteDatabase.CONFLICT_IGNORE); - } - } - - private @NonNull JobSpec jobSpecFromCursor(@NonNull Cursor cursor) { - return new JobSpec(cursor.getString(cursor.getColumnIndexOrThrow(Jobs.JOB_SPEC_ID)), - cursor.getString(cursor.getColumnIndexOrThrow(Jobs.FACTORY_KEY)), - cursor.getString(cursor.getColumnIndexOrThrow(Jobs.QUEUE_KEY)), - cursor.getLong(cursor.getColumnIndexOrThrow(Jobs.CREATE_TIME)), - cursor.getLong(cursor.getColumnIndexOrThrow(Jobs.NEXT_RUN_ATTEMPT_TIME)), - cursor.getInt(cursor.getColumnIndexOrThrow(Jobs.RUN_ATTEMPT)), - cursor.getInt(cursor.getColumnIndexOrThrow(Jobs.MAX_ATTEMPTS)), - cursor.getLong(cursor.getColumnIndexOrThrow(Jobs.MAX_BACKOFF)), - cursor.getLong(cursor.getColumnIndexOrThrow(Jobs.LIFESPAN)), - cursor.getInt(cursor.getColumnIndexOrThrow(Jobs.MAX_INSTANCES)), - cursor.getString(cursor.getColumnIndexOrThrow(Jobs.SERIALIZED_DATA)), - cursor.getInt(cursor.getColumnIndexOrThrow(Jobs.IS_RUNNING)) == 1); - } - - private @NonNull ConstraintSpec constraintSpecFromCursor(@NonNull Cursor cursor) { - return new ConstraintSpec(cursor.getString(cursor.getColumnIndexOrThrow(Constraints.JOB_SPEC_ID)), - cursor.getString(cursor.getColumnIndexOrThrow(Constraints.FACTORY_KEY))); - } - - private @NonNull DependencySpec dependencySpecFromCursor(@NonNull Cursor cursor) { - return new DependencySpec(cursor.getString(cursor.getColumnIndexOrThrow(Dependencies.JOB_SPEC_ID)), - cursor.getString(cursor.getColumnIndexOrThrow(Dependencies.DEPENDS_ON_JOB_SPEC_ID))); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessagingDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MessagingDatabase.java index d3ba31747d..edc6bc1a6f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessagingDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessagingDatabase.java @@ -37,6 +37,13 @@ public abstract class MessagingDatabase extends Database implements MmsSmsColumn public abstract void markExpireStarted(long messageId, long startTime); public abstract void markAsSent(long messageId, boolean secure); + + public abstract void markAsSyncing(long id); + + public abstract void markAsResyncing(long id); + + public abstract void markAsSyncFailed(long id); + public abstract void markUnidentified(long messageId, boolean unidentified); public abstract void markAsDeleted(long messageId, boolean read, boolean hasMention); @@ -199,7 +206,6 @@ public abstract class MessagingDatabase extends Database implements MmsSmsColumn contentValues.put(THREAD_ID, newThreadId); db.update(getTableName(), contentValues, where, args); } - public static class SyncMessageId { private final Address address; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt index 90d3cad454..e8f65dae06 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt @@ -60,11 +60,13 @@ import org.thoughtcrime.securesms.database.SmsDatabase.InsertListener import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord import org.thoughtcrime.securesms.database.model.MessageRecord +import org.thoughtcrime.securesms.database.model.MmsMessageRecord import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord import org.thoughtcrime.securesms.database.model.Quote import org.thoughtcrime.securesms.dependencies.DatabaseComponent.Companion.get import org.thoughtcrime.securesms.mms.MmsException import org.thoughtcrime.securesms.mms.SlideDeck +import org.thoughtcrime.securesms.util.asSequence import java.io.Closeable import java.io.IOException import java.security.SecureRandom @@ -91,54 +93,22 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa return 0 } - fun addFailures(messageId: Long, failure: List) { - try { - addToDocument(messageId, NETWORK_FAILURE, failure, NetworkFailureList::class.java) - } catch (e: IOException) { - Log.w(TAG, e) + fun isOutgoingMessage(timestamp: Long): Boolean = + databaseHelper.writableDatabase.query( + TABLE_NAME, + arrayOf(ID, THREAD_ID, MESSAGE_BOX, ADDRESS), + DATE_SENT + " = ?", + arrayOf(timestamp.toString()), + null, + null, + null, + null + ).use { cursor -> + cursor.asSequence() + .map { cursor.getColumnIndexOrThrow(MESSAGE_BOX) } + .map(cursor::getLong) + .any { MmsSmsColumns.Types.isOutgoingMessageType(it) } } - } - - fun removeFailure(messageId: Long, failure: NetworkFailure?) { - try { - removeFromDocument(messageId, NETWORK_FAILURE, failure, NetworkFailureList::class.java) - } catch (e: IOException) { - Log.w(TAG, e) - } - } - - fun isOutgoingMessage(timestamp: Long): Boolean { - val database = databaseHelper.writableDatabase - var cursor: Cursor? = null - var isOutgoing = false - try { - cursor = database.query( - TABLE_NAME, - arrayOf(ID, THREAD_ID, MESSAGE_BOX, ADDRESS), - DATE_SENT + " = ?", - arrayOf(timestamp.toString()), - null, - null, - null, - null - ) - while (cursor.moveToNext()) { - if (MmsSmsColumns.Types.isOutgoingMessageType( - cursor.getLong( - cursor.getColumnIndexOrThrow( - MESSAGE_BOX - ) - ) - ) - ) { - isOutgoing = true - } - } - } finally { - cursor?.close() - } - return isOutgoing - } fun incrementReceiptCount( messageId: SyncMessageId, @@ -254,15 +224,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa } } - private fun getThreadIdFor(notification: NotificationInd): Long { - val fromString = - if (notification.from != null && notification.from.textString != null) toIsoString( - notification.from.textString - ) else "" - val recipient = Recipient.from(context, fromExternal(context, fromString), false) - return get(context).threadDatabase().getOrCreateThreadIdFor(recipient) - } - private fun rawQuery(where: String, arguments: Array?): Cursor { val database = databaseHelper.readableDatabase return database.rawQuery( @@ -273,10 +234,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa ) } - fun getMessages(idsAsString: String): Cursor { - return rawQuery(idsAsString, null) - } - fun getMessage(messageId: Long): Cursor { val cursor = rawQuery(RAW_ID_WHERE, arrayOf(messageId.toString())) setNotifyConverationListeners(cursor, getThreadIdForMessage(messageId)) @@ -306,48 +263,40 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa } } - fun markAsPendingInsecureSmsFallback(messageId: Long) { - val threadId = getThreadIdForMessage(messageId) + private fun markAs( + messageId: Long, + baseType: Long, + threadId: Long = getThreadIdForMessage(messageId) + ) { updateMailboxBitmask( messageId, MmsSmsColumns.Types.BASE_TYPE_MASK, - MmsSmsColumns.Types.BASE_PENDING_INSECURE_SMS_FALLBACK, + baseType, Optional.of(threadId) ) notifyConversationListeners(threadId) } + override fun markAsSyncing(messageId: Long) { + markAs(messageId, MmsSmsColumns.Types.BASE_SYNCING_TYPE) + } + override fun markAsResyncing(messageId: Long) { + markAs(messageId, MmsSmsColumns.Types.BASE_RESYNCING_TYPE) + } + override fun markAsSyncFailed(messageId: Long) { + markAs(messageId, MmsSmsColumns.Types.BASE_SYNC_FAILED_TYPE) + } + fun markAsSending(messageId: Long) { - val threadId = getThreadIdForMessage(messageId) - updateMailboxBitmask( - messageId, - MmsSmsColumns.Types.BASE_TYPE_MASK, - MmsSmsColumns.Types.BASE_SENDING_TYPE, - Optional.of(threadId) - ) - notifyConversationListeners(threadId) + markAs(messageId, MmsSmsColumns.Types.BASE_SENDING_TYPE) } fun markAsSentFailed(messageId: Long) { - val threadId = getThreadIdForMessage(messageId) - updateMailboxBitmask( - messageId, - MmsSmsColumns.Types.BASE_TYPE_MASK, - MmsSmsColumns.Types.BASE_SENT_FAILED_TYPE, - Optional.of(threadId) - ) - notifyConversationListeners(threadId) + markAs(messageId, MmsSmsColumns.Types.BASE_SENT_FAILED_TYPE) } override fun markAsSent(messageId: Long, secure: Boolean) { - val threadId = getThreadIdForMessage(messageId) - updateMailboxBitmask( - messageId, - MmsSmsColumns.Types.BASE_TYPE_MASK, - MmsSmsColumns.Types.BASE_SENT_TYPE or if (secure) MmsSmsColumns.Types.PUSH_MESSAGE_BIT or MmsSmsColumns.Types.SECURE_MESSAGE_BIT else 0, - Optional.of(threadId) - ) - notifyConversationListeners(threadId) + markAs(messageId, MmsSmsColumns.Types.BASE_SENT_TYPE or if (secure) MmsSmsColumns.Types.PUSH_MESSAGE_BIT or MmsSmsColumns.Types.SECURE_MESSAGE_BIT else 0) } override fun markUnidentified(messageId: Long, unidentified: Boolean) { @@ -371,13 +320,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa val mentionChange = if (hasMention) { 1 } else { 0 } get(context).threadDatabase().decrementUnread(threadId, 1, mentionChange) } - updateMailboxBitmask( - messageId, - MmsSmsColumns.Types.BASE_TYPE_MASK, - MmsSmsColumns.Types.BASE_DELETED_TYPE, - Optional.of(threadId) - ) - notifyConversationListeners(threadId) + markAs(messageId, MmsSmsColumns.Types.BASE_DELETED_TYPE, threadId) } override fun markExpireStarted(messageId: Long) { @@ -407,10 +350,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa ) } - fun setAllMessagesRead(): List { - return setMessagesRead(READ + " = 0", null) - } - private fun setMessagesRead(where: String, arguments: Array?): List { val database = databaseHelper.writableDatabase val result: MutableList = LinkedList() @@ -419,7 +358,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa try { cursor = database.query( TABLE_NAME, - arrayOf(ID, ADDRESS, DATE_SENT, MESSAGE_BOX, EXPIRES_IN, EXPIRE_STARTED), + arrayOf(ID, ADDRESS, DATE_SENT, MESSAGE_BOX, EXPIRES_IN, EXPIRE_STARTED), where, arguments, null, @@ -1400,25 +1339,16 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa val attachments = get(context).attachmentDatabase().getAttachment( cursor ) - val contacts: List = getSharedContacts( - cursor, attachments - ) - val contactAttachments = - contacts.map { obj: Contact? -> obj!!.avatarAttachment } - .filter { a: Attachment? -> a != null } - .toSet() - val previews: List = getLinkPreviews( - cursor, attachments - ) - val previewAttachments = - previews.filter { lp: LinkPreview? -> lp!!.getThumbnail().isPresent } - .map { lp: LinkPreview? -> lp!!.getThumbnail().get() } - .toSet() + val contacts: List = getSharedContacts(cursor, attachments) + val contactAttachments: Set = + contacts.mapNotNull { it?.avatarAttachment }.toSet() + val previews: List = getLinkPreviews(cursor, attachments) + val previewAttachments: Set = + previews.mapNotNull { it?.getThumbnail()?.orNull() }.toSet() val slideDeck = getSlideDeck( - Stream.of(attachments) - .filterNot { o: DatabaseAttachment? -> contactAttachments.contains(o) } - .filterNot { o: DatabaseAttachment? -> previewAttachments.contains(o) } - .toList() + attachments + .filterNot { o: DatabaseAttachment? -> o in contactAttachments } + .filterNot { o: DatabaseAttachment? -> o in previewAttachments } ) val quote = getQuote(cursor) val reactions = get(context).reactionDatabase().getReactions(cursor) @@ -1476,11 +1406,13 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa val retrievedQuote = get(context).mmsSmsDatabase().getMessageFor(quoteId, quoteAuthor) val quoteText = retrievedQuote?.body val quoteMissing = retrievedQuote == null - val attachments = get(context).attachmentDatabase().getAttachment(cursor) - val quoteAttachments: List? = - Stream.of(attachments).filter { obj: DatabaseAttachment? -> obj!!.isQuote } + val quoteDeck = ( + (retrievedQuote as? MmsMessageRecord)?.slideDeck ?: + Stream.of(get(context).attachmentDatabase().getAttachment(cursor)) + .filter { obj: DatabaseAttachment? -> obj!!.isQuote } .toList() - val quoteDeck = SlideDeck(context, quoteAttachments!!) + .let { SlideDeck(context, it) } + ) return Quote( quoteId, fromExternal(context, quoteAuthor), @@ -1623,4 +1555,4 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa const val CREATE_REACTIONS_LAST_SEEN_COMMAND = "ALTER TABLE $TABLE_NAME ADD COLUMN $REACTIONS_LAST_SEEN INTEGER DEFAULT 0;" const val CREATE_HAS_MENTION_COMMAND = "ALTER TABLE $TABLE_NAME ADD COLUMN $HAS_MENTION INTEGER DEFAULT 0;" } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java index f3110a5c79..1e1cc50896 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsColumns.java @@ -47,8 +47,13 @@ public interface MmsSmsColumns { protected static final long BASE_PENDING_INSECURE_SMS_FALLBACK = 26; public static final long BASE_DRAFT_TYPE = 27; protected static final long BASE_DELETED_TYPE = 28; + protected static final long BASE_SYNCING_TYPE = 29; + protected static final long BASE_RESYNCING_TYPE = 30; + protected static final long BASE_SYNC_FAILED_TYPE = 31; protected static final long[] OUTGOING_MESSAGE_TYPES = {BASE_OUTBOX_TYPE, BASE_SENT_TYPE, + BASE_SYNCING_TYPE, BASE_RESYNCING_TYPE, + BASE_SYNC_FAILED_TYPE, BASE_SENDING_TYPE, BASE_SENT_FAILED_TYPE, BASE_PENDING_SECURE_SMS_FALLBACK, BASE_PENDING_INSECURE_SMS_FALLBACK, @@ -109,6 +114,18 @@ public interface MmsSmsColumns { return (type & BASE_TYPE_MASK) == BASE_DRAFT_TYPE; } + public static boolean isResyncingType(long type) { + return (type & BASE_TYPE_MASK) == BASE_RESYNCING_TYPE; + } + + public static boolean isSyncingType(long type) { + return (type & BASE_TYPE_MASK) == BASE_SYNCING_TYPE; + } + + public static boolean isSyncFailedMessageType(long type) { + return (type & BASE_TYPE_MASK) == BASE_SYNC_FAILED_TYPE; + } + public static boolean isFailedMessageType(long type) { return (type & BASE_TYPE_MASK) == BASE_SENT_FAILED_TYPE; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java index af2faaaca9..e3570fd283 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java @@ -276,7 +276,7 @@ public class RecipientDatabase extends Database { notifyRecipientListeners(); } - public void setBlocked(@NonNull List recipients, boolean blocked) { + public void setBlocked(@NonNull Iterable recipients, boolean blocked) { SQLiteDatabase db = getWritableDatabase(); db.beginTransaction(); try { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SessionJobDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/SessionJobDatabase.kt index 66497d9da8..b081fb007e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SessionJobDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SessionJobDatabase.kt @@ -46,7 +46,7 @@ class SessionJobDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa databaseHelper.writableDatabase.delete(sessionJobTable, "${Companion.jobID} = ?", arrayOf( jobID )) } - fun getAllPendingJobs(type: String): Map { + fun getAllJobs(type: String): Map { val database = databaseHelper.readableDatabase return database.getAll(sessionJobTable, "$jobType = ?", arrayOf( type )) { cursor -> val jobID = cursor.getString(jobID) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java index 0d61b26796..42a00ccbb2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -202,6 +202,21 @@ public class SmsDatabase extends MessagingDatabase { updateTypeBitmask(id, Types.BASE_TYPE_MASK, Types.BASE_SENDING_TYPE); } + @Override + public void markAsSyncing(long id) { + updateTypeBitmask(id, Types.BASE_TYPE_MASK, Types.BASE_SYNCING_TYPE); + } + + @Override + public void markAsResyncing(long id) { + updateTypeBitmask(id, Types.BASE_TYPE_MASK, Types.BASE_RESYNCING_TYPE); + } + + @Override + public void markAsSyncFailed(long id) { + updateTypeBitmask(id, Types.BASE_TYPE_MASK, Types.BASE_SYNC_FAILED_TYPE); + } + @Override public void markUnidentified(long id, boolean unidentified) { ContentValues contentValues = new ContentValues(1); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 076fa57afc..365c12b839 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -42,13 +42,12 @@ import org.session.libsignal.messages.SignalServiceGroup import org.session.libsignal.utilities.IdPrefix import org.session.libsignal.utilities.KeyHelper import org.session.libsignal.utilities.guava.Optional -import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper import org.thoughtcrime.securesms.database.model.MessageId import org.thoughtcrime.securesms.database.model.ReactionRecord import org.thoughtcrime.securesms.dependencies.DatabaseComponent import org.thoughtcrime.securesms.groups.OpenGroupManager -import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob +import org.session.libsession.messaging.jobs.RetrieveProfileAvatarJob import org.thoughtcrime.securesms.mms.PartAuthority import org.thoughtcrime.securesms.util.SessionMetaProtocol import java.security.MessageDigest @@ -70,13 +69,9 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, return Profile(displayName, profileKey, profilePictureUrl) } - override fun setUserProfilePictureURL(newValue: String) { - val ourRecipient = fromSerialized(getUserPublicKey()!!).let { - Recipient.from(context, it, false) - } - TextSecurePreferences.setProfilePictureURL(context, newValue) - RetrieveProfileAvatarJob(ourRecipient, newValue) - ApplicationContext.getInstance(context).jobManager.add(RetrieveProfileAvatarJob(ourRecipient, newValue)) + override fun setProfileAvatar(recipient: Recipient, profileAvatar: String?) { + val database = DatabaseComponent.get(context).recipientDatabase() + database.setProfileAvatar(recipient, profileAvatar) } override fun getOrGenerateRegistrationID(): Int { @@ -211,7 +206,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, } override fun getAllPendingJobs(type: String): Map { - return DatabaseComponent.get(context).sessionJobDatabase().getAllPendingJobs(type) + return DatabaseComponent.get(context).sessionJobDatabase().getAllJobs(type) } override fun getAttachmentUploadJob(attachmentID: Long): AttachmentUploadJob? { @@ -377,6 +372,22 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, } } + override fun markAsSyncing(timestamp: Long, author: String) { + DatabaseComponent.get(context).mmsSmsDatabase() + .getMessageFor(timestamp, author) + ?.run { getMmsDatabaseElseSms(isMms).markAsSyncing(id) } + } + + private fun getMmsDatabaseElseSms(isMms: Boolean) = + if (isMms) DatabaseComponent.get(context).mmsDatabase() + else DatabaseComponent.get(context).smsDatabase() + + override fun markAsResyncing(timestamp: Long, author: String) { + DatabaseComponent.get(context).mmsSmsDatabase() + .getMessageFor(timestamp, author) + ?.run { getMmsDatabaseElseSms(isMms).markAsResyncing(id) } + } + override fun markAsSending(timestamp: Long, author: String) { val database = DatabaseComponent.get(context).mmsSmsDatabase() val messageRecord = database.getMessageFor(timestamp, author) ?: return @@ -402,7 +413,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, } } - override fun setErrorMessage(timestamp: Long, author: String, error: Exception) { + override fun markAsSentFailed(timestamp: Long, author: String, error: Exception) { val database = DatabaseComponent.get(context).mmsSmsDatabase() val messageRecord = database.getMessageFor(timestamp, author) ?: return if (messageRecord.isMms) { @@ -425,6 +436,26 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, } } + override fun markAsSyncFailed(timestamp: Long, author: String, error: Exception) { + val database = DatabaseComponent.get(context).mmsSmsDatabase() + val messageRecord = database.getMessageFor(timestamp, author) ?: return + + database.getMessageFor(timestamp, author) + ?.run { getMmsDatabaseElseSms(isMms).markAsSyncFailed(id) } + + if (error.localizedMessage != null) { + val message: String + if (error is OnionRequestAPI.HTTPRequestFailedAtDestinationException && error.statusCode == 429) { + message = "429: Rate limited." + } else { + message = error.localizedMessage!! + } + DatabaseComponent.get(context).lokiMessageDatabase().setErrorMessage(messageRecord.getId(), message) + } else { + DatabaseComponent.get(context).lokiMessageDatabase().setErrorMessage(messageRecord.getId(), error.javaClass.simpleName) + } + } + override fun clearErrorMessage(messageID: Long) { val db = DatabaseComponent.get(context).lokiMessageDatabase() db.clearErrorMessage(messageID) @@ -677,8 +708,10 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, recipientDatabase.setApproved(recipient, true) threadDatabase.setHasSent(threadId, true) } - if (contact.isBlocked == true) { - recipientDatabase.setBlocked(recipient, true) + + val contactIsBlocked: Boolean? = contact.isBlocked + if (contactIsBlocked != null && recipient.isBlocked != contactIsBlocked) { + recipientDatabase.setBlocked(recipient, contactIsBlocked) threadDatabase.deleteConversation(threadId) } } @@ -707,6 +740,11 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, return mmsSmsDb.getConversationCount(threadID) } + override fun deleteConversation(threadId: Long) { + val threadDB = DatabaseComponent.get(context).threadDatabase() + threadDB.deleteConversation(threadId) + } + override fun getAttachmentDataUri(attachmentId: AttachmentId): Uri { @@ -974,7 +1012,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, DatabaseComponent.get(context).reactionDatabase().deleteMessageReactions(MessageId(messageId, mms)) } - override fun unblock(toUnblock: List) { + override fun unblock(toUnblock: Iterable) { val recipientDb = DatabaseComponent.get(context).recipientDatabase() recipientDb.setBlocked(toUnblock, false) } @@ -983,5 +1021,4 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, val recipientDb = DatabaseComponent.get(context).recipientDatabase() return recipientDb.blockedContacts } - } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index df69c239fc..8a4473b409 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -24,7 +24,6 @@ import org.thoughtcrime.securesms.database.EmojiSearchDatabase; import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupMemberDatabase; import org.thoughtcrime.securesms.database.GroupReceiptDatabase; -import org.thoughtcrime.securesms.database.JobDatabase; import org.thoughtcrime.securesms.database.LokiAPIDatabase; import org.thoughtcrime.securesms.database.LokiBackupFilesDatabase; import org.thoughtcrime.securesms.database.LokiMessageDatabase; @@ -284,9 +283,6 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { for (String sql : SearchDatabase.CREATE_TABLE) { db.execSQL(sql); } - for (String sql : JobDatabase.CREATE_TABLE) { - db.execSQL(sql); - } db.execSQL(LokiAPIDatabase.getCreateSnodePoolTableCommand()); db.execSQL(LokiAPIDatabase.getCreateOnionRequestPathTableCommand()); db.execSQL(LokiAPIDatabase.getCreateSwarmTableCommand()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java index ef0f4b54f3..39fba182aa 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/DisplayRecord.java @@ -80,6 +80,18 @@ public abstract class DisplayRecord { return !isFailed() && !isPending(); } + public boolean isSyncing() { + return MmsSmsColumns.Types.isSyncingType(type); + } + + public boolean isResyncing() { + return MmsSmsColumns.Types.isResyncingType(type); + } + + public boolean isSyncFailed() { + return MmsSmsColumns.Types.isSyncFailedMessageType(type); + } + public boolean isFailed() { return MmsSmsColumns.Types.isFailedMessageType(type) || MmsSmsColumns.Types.isPendingSecureSmsFallbackType(type) diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/DatabaseComponent.kt b/app/src/main/java/org/thoughtcrime/securesms/dependencies/DatabaseComponent.kt index 648b9c43ec..60d31a19d4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/DatabaseComponent.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/DatabaseComponent.kt @@ -32,7 +32,6 @@ interface DatabaseComponent { fun recipientDatabase(): RecipientDatabase fun groupReceiptDatabase(): GroupReceiptDatabase fun searchDatabase(): SearchDatabase - fun jobDatabase(): JobDatabase fun lokiAPIDatabase(): LokiAPIDatabase fun lokiMessageDatabase(): LokiMessageDatabase fun lokiThreadDatabase(): LokiThreadDatabase diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/DatabaseModule.kt b/app/src/main/java/org/thoughtcrime/securesms/dependencies/DatabaseModule.kt index fba7a7e503..3372e10330 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/DatabaseModule.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/DatabaseModule.kt @@ -86,10 +86,6 @@ object DatabaseModule { @Singleton fun searchDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = SearchDatabase(context,openHelper) - @Provides - @Singleton - fun provideJobDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = JobDatabase(context, openHelper) - @Provides @Singleton fun provideLokiApiDatabase(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = LokiAPIDatabase(context,openHelper) diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt index ef47269107..dbdf2615ae 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/OpenGroupManager.kt @@ -15,7 +15,7 @@ import java.util.concurrent.Executors object OpenGroupManager { private val executorService = Executors.newScheduledThreadPool(4) - private var pollers = mutableMapOf() // One for each server + private val pollers = mutableMapOf() // One for each server private var isPolling = false private val pollUpdaterLock = Any() @@ -41,11 +41,11 @@ object OpenGroupManager { isPolling = true val storage = MessagingModuleConfiguration.shared.storage val servers = storage.getAllOpenGroups().values.map { it.server }.toSet() - servers.forEach { server -> - pollers[server]?.stop() // Shouldn't be necessary - val poller = OpenGroupPoller(server, executorService) - poller.startIfNeeded() - pollers[server] = poller + synchronized(pollUpdaterLock) { + servers.forEach { server -> + pollers[server]?.stop() // Shouldn't be necessary + pollers[server] = OpenGroupPoller(server, executorService).apply { startIfNeeded() } + } } } @@ -60,7 +60,7 @@ object OpenGroupManager { @WorkerThread fun add(server: String, room: String, publicKey: String, context: Context): OpenGroupApi.RoomInfo? { val openGroupID = "$server.$room" - var threadID = GroupManager.getOpenGroupThreadID(openGroupID, context) + val threadID = GroupManager.getOpenGroupThreadID(openGroupID, context) val storage = MessagingModuleConfiguration.shared.storage val threadDB = DatabaseComponent.get(context).lokiThreadDatabase() // Check it it's added already @@ -76,13 +76,16 @@ object OpenGroupManager { // Get capabilities & room info val (capabilities, info) = OpenGroupApi.getCapabilitiesAndRoomInfo(room, server).get() storage.setServerCapabilities(server, capabilities.capabilities) - storage.setUserCount(room, server, info.activeUsers) // Create the group locally if not available already if (threadID < 0) { - threadID = GroupManager.createOpenGroup(openGroupID, context, null, info.name).threadId + GroupManager.createOpenGroup(openGroupID, context, null, info.name) } - val openGroup = OpenGroup(server = server, room = room, publicKey = publicKey, name = info.name, imageId = info.imageId, canWrite = info.write, infoUpdates = info.infoUpdates) - threadDB.setOpenGroupChat(openGroup, threadID) + OpenGroupPoller.handleRoomPollInfo( + server = server, + roomToken = room, + pollInfo = info.toPollInfo(), + createGroupIfMissingWithPublicKey = publicKey + ) return info } diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt index fc85f544fe..7e9d2640a1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt @@ -88,7 +88,6 @@ class ConversationOptionsBottomSheet(private val parentContext: Context) : Botto override fun onStart() { super.onStart() val window = dialog?.window ?: return - val isLightMode = UiModeUtilities.isDayUiMode(requireContext()) - window.setDimAmount(if (isLightMode) 0.1f else 0.75f) + window.setDimAmount(0.6f) } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index 72df057985..5744178576 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -495,6 +495,8 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), .setPositiveButton(R.string.RecipientPreferenceActivity_block) { dialog, _ -> lifecycleScope.launch(Dispatchers.IO) { recipientDatabase.setBlocked(thread.recipient, true) + // TODO: Remove in UserConfig branch + ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@HomeActivity) withContext(Dispatchers.Main) { binding.recyclerView.adapter!!.notifyDataSetChanged() dialog.dismiss() @@ -511,6 +513,8 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), .setPositiveButton(R.string.RecipientPreferenceActivity_unblock) { dialog, _ -> lifecycleScope.launch(Dispatchers.IO) { recipientDatabase.setBlocked(thread.recipient, false) + // TODO: Remove in UserConfig branch + ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@HomeActivity) withContext(Dispatchers.Main) { binding.recyclerView.adapter!!.notifyDataSetChanged() dialog.dismiss() diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/UserDetailsBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/home/UserDetailsBottomSheet.kt index f3915abff6..bc9a9beced 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/UserDetailsBottomSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/UserDetailsBottomSheet.kt @@ -117,8 +117,7 @@ class UserDetailsBottomSheet: BottomSheetDialogFragment() { override fun onStart() { super.onStart() val window = dialog?.window ?: return - val isLightMode = UiModeUtilities.isDayUiMode(requireContext()) - window.setDimAmount(if (isLightMode) 0.1f else 0.75f) + window.setDimAmount(0.6f) } fun saveNickName(recipient: Recipient) = with(binding) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/AlarmManagerScheduler.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/AlarmManagerScheduler.java deleted file mode 100644 index dc1d2afcf1..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/AlarmManagerScheduler.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import android.app.AlarmManager; -import android.app.Application; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import androidx.annotation.NonNull; - -import com.annimon.stream.Stream; - -import org.session.libsignal.utilities.Log; -import org.thoughtcrime.securesms.ApplicationContext; - -import java.util.List; -import java.util.UUID; - -import network.loki.messenger.BuildConfig; - -/** - * Schedules tasks using the {@link AlarmManager}. - * - * Given that this scheduler is only used when {@link KeepAliveService} is also used (which keeps - * all of the {@link ConstraintObserver}s running), this only needs to schedule future runs in - * situations where all constraints are already met. Otherwise, the {@link ConstraintObserver}s will - * trigger future runs when the constraints are met. - * - * For the same reason, this class also doesn't have to schedule jobs that don't have delays. - * - * Important: Only use on API < 26. - */ -public class AlarmManagerScheduler implements Scheduler { - - private static final String TAG = AlarmManagerScheduler.class.getSimpleName(); - - private final Application application; - - AlarmManagerScheduler(@NonNull Application application) { - this.application = application; - } - - @Override - public void schedule(long delay, @NonNull List constraints) { - if (delay > 0 && Stream.of(constraints).allMatch(Constraint::isMet)) { - setUniqueAlarm(application, System.currentTimeMillis() + delay); - } - } - - private void setUniqueAlarm(@NonNull Context context, long time) { - AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - Intent intent = new Intent(context, RetryReceiver.class); - - intent.setAction(BuildConfig.APPLICATION_ID + UUID.randomUUID().toString()); - alarmManager.set(AlarmManager.RTC_WAKEUP, time, PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)); - - Log.i(TAG, "Set an alarm to retry a job in " + (time - System.currentTimeMillis()) + " ms."); - } - - public static class RetryReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - Log.i(TAG, "Received an alarm to retry a job."); - ApplicationContext.getInstance(context).getJobManager().wakeUp(); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/CompositeScheduler.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/CompositeScheduler.java deleted file mode 100644 index 322366f4f4..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/CompositeScheduler.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import androidx.annotation.NonNull; - -import java.util.Arrays; -import java.util.List; - -class CompositeScheduler implements Scheduler { - - private final List schedulers; - - CompositeScheduler(@NonNull Scheduler... schedulers) { - this.schedulers = Arrays.asList(schedulers); - } - - @Override - public void schedule(long delay, @NonNull List constraints) { - for (Scheduler scheduler : schedulers) { - scheduler.schedule(delay, constraints); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintInstantiator.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintInstantiator.java deleted file mode 100644 index b0a67e3d19..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintInstantiator.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import androidx.annotation.NonNull; - -import java.util.HashMap; -import java.util.Map; - -public class ConstraintInstantiator { - - private final Map constraintFactories; - - ConstraintInstantiator(@NonNull Map constraintFactories) { - this.constraintFactories = new HashMap<>(constraintFactories); - } - - public @NonNull Constraint instantiate(@NonNull String constraintFactoryKey) { - if (constraintFactories.containsKey(constraintFactoryKey)) { - return constraintFactories.get(constraintFactoryKey).create(); - } else { - throw new IllegalStateException("Tried to instantiate a constraint with key '" + constraintFactoryKey + "', but no matching factory was found."); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintObserver.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintObserver.java deleted file mode 100644 index fd7f4fd43c..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ConstraintObserver.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import androidx.annotation.NonNull; - -public interface ConstraintObserver { - - void register(@NonNull Notifier notifier); - - interface Notifier { - void onConstraintMet(@NonNull String reason); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/DependencyInjector.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/DependencyInjector.java deleted file mode 100644 index c8a266bd87..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/DependencyInjector.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright (C) 2014 Open Whisper Systems - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.thoughtcrime.securesms.jobmanager; - -/** - * Interface responsible for injecting dependencies into Jobs. - */ -public interface DependencyInjector { - void injectDependencies(Object object); -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ExecutorFactory.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ExecutorFactory.java deleted file mode 100644 index b0c2b974de..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/ExecutorFactory.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import androidx.annotation.NonNull; - -import java.util.concurrent.ExecutorService; - -public interface ExecutorFactory { - @NonNull ExecutorService newSingleThreadExecutor(@NonNull String name); -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/InAppScheduler.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/InAppScheduler.java deleted file mode 100644 index b0f314eaa6..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/InAppScheduler.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import android.os.Handler; -import android.os.HandlerThread; -import androidx.annotation.NonNull; - -import com.annimon.stream.Stream; - -import org.session.libsignal.utilities.Log; - -import java.util.List; - -/** - * Schedules future runs on an in-app handler. Intended to be used in combination with a persistent - * {@link Scheduler} to improve responsiveness when the app is open. - * - * This should only schedule runs when all constraints are met. Because this only works when the - * app is foregrounded, jobs that don't have their constraints met will be run when the relevant - * {@link ConstraintObserver} is triggered. - * - * Similarly, this does not need to schedule retries with no delay, as this doesn't provide any - * persistence, and other mechanisms will take care of that. - */ -class InAppScheduler implements Scheduler { - - private static final String TAG = InAppScheduler.class.getSimpleName(); - - private final JobManager jobManager; - private final Handler handler; - - InAppScheduler(@NonNull JobManager jobManager) { - HandlerThread handlerThread = new HandlerThread("InAppScheduler"); - handlerThread.start(); - - this.jobManager = jobManager; - this.handler = new Handler(handlerThread.getLooper()); - } - - @Override - public void schedule(long delay, @NonNull List constraints) { - if (delay > 0 && Stream.of(constraints).allMatch(Constraint::isMet)) { - Log.i(TAG, "Scheduling a retry in " + delay + " ms."); - handler.postDelayed(() -> { - Log.i(TAG, "Triggering a job retry."); - jobManager.wakeUp(); - }, delay); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Job.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Job.java deleted file mode 100644 index 990207779d..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Job.java +++ /dev/null @@ -1,286 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import android.content.Context; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.WorkerThread; - -import org.session.libsession.messaging.utilities.Data; -import org.session.libsignal.utilities.Log; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -/** - * A durable unit of work. - * - * Jobs have {@link Parameters} that describe the conditions upon when you'd like them to run, how - * often they should be retried, and how long they should be retried for. - * - * Never rely on a specific instance of this class being run. It can be created and destroyed as the - * job is retried. State that you want to save is persisted to a {@link Data} object in - * {@link #serialize()}. Your job is then recreated using a {@link Factory} that you register in - * {@link JobManager.Configuration.Builder#setJobFactories(Map)}, which is given the saved - * {@link Data} bundle. - * - * @deprecated - * use WorkManager - * API instead. - */ -public abstract class Job { - - private static final String TAG = Log.tag(Job.class); - - private final Parameters parameters; - - private String id; - private int runAttempt; - private long nextRunAttemptTime; - - protected Context context; - - public Job(@NonNull Parameters parameters) { - this.parameters = parameters; - } - - public final String getId() { - return id; - } - - public final @NonNull Parameters getParameters() { - return parameters; - } - - public final int getRunAttempt() { - return runAttempt; - } - - public final long getNextRunAttemptTime() { - return nextRunAttemptTime; - } - - /** - * This is already called by {@link JobController} during job submission, but if you ever run a - * job without submitting it to the {@link JobManager}, then you'll need to invoke this yourself. - */ - public final void setContext(@NonNull Context context) { - this.context = context; - } - - /** Should only be invoked by {@link JobController} */ - final void setId(@NonNull String id) { - this.id = id; - } - - /** Should only be invoked by {@link JobController} */ - final void setRunAttempt(int runAttempt) { - this.runAttempt = runAttempt; - } - - /** Should only be invoked by {@link JobController} */ - final void setNextRunAttemptTime(long nextRunAttemptTime) { - this.nextRunAttemptTime = nextRunAttemptTime; - } - - @WorkerThread - final void onSubmit() { - Log.i(TAG, JobLogger.format(this, "onSubmit()")); - onAdded(); - } - - /** - * Called when the job is first submitted to the {@link JobManager}. - */ - @WorkerThread - public void onAdded() { - } - - /** - * Called after a job has run and its determined that a retry is required. - */ - @WorkerThread - public void onRetry() { - } - - /** - * Serialize your job state so that it can be recreated in the future. - */ - public abstract @NonNull Data serialize(); - - /** - * Returns the key that can be used to find the relevant factory needed to create your job. - */ - public abstract @NonNull String getFactoryKey(); - - /** - * Called to do your actual work. - */ - @WorkerThread - public abstract @NonNull Result run(); - - /** - * Called when your job has completely failed. - */ - @WorkerThread - public abstract void onCanceled(); - - public interface Factory { - @NonNull T create(@NonNull Parameters parameters, @NonNull Data data); - } - - public enum Result { - SUCCESS, FAILURE, RETRY - } - - public static final class Parameters { - - public static final int IMMORTAL = -1; - public static final int UNLIMITED = -1; - - private final long createTime; - private final long lifespan; - private final int maxAttempts; - private final long maxBackoff; - private final int maxInstances; - private final String queue; - private final List constraintKeys; - - private Parameters(long createTime, - long lifespan, - int maxAttempts, - long maxBackoff, - int maxInstances, - @Nullable String queue, - @NonNull List constraintKeys) - { - this.createTime = createTime; - this.lifespan = lifespan; - this.maxAttempts = maxAttempts; - this.maxBackoff = maxBackoff; - this.maxInstances = maxInstances; - this.queue = queue; - this.constraintKeys = constraintKeys; - } - - public long getCreateTime() { - return createTime; - } - - public long getLifespan() { - return lifespan; - } - - public int getMaxAttempts() { - return maxAttempts; - } - - public long getMaxBackoff() { - return maxBackoff; - } - - public int getMaxInstances() { - return maxInstances; - } - - public @Nullable String getQueue() { - return queue; - } - - public List getConstraintKeys() { - return constraintKeys; - } - - - public static final class Builder { - - private long createTime = System.currentTimeMillis(); - private long maxBackoff = TimeUnit.SECONDS.toMillis(30); - private long lifespan = IMMORTAL; - private int maxAttempts = 1; - private int maxInstances = UNLIMITED; - private String queue = null; - private List constraintKeys = new LinkedList<>(); - - /** Should only be invoked by {@link JobController} */ - Builder setCreateTime(long createTime) { - this.createTime = createTime; - return this; - } - - /** - * Specify the amount of time this job is allowed to be retried. Defaults to {@link #IMMORTAL}. - */ - public @NonNull Builder setLifespan(long lifespan) { - this.lifespan = lifespan; - return this; - } - - /** - * Specify the maximum number of times you want to attempt this job. Defaults to 1. - */ - public @NonNull Builder setMaxAttempts(int maxAttempts) { - this.maxAttempts = maxAttempts; - return this; - } - - /** - * Specify the longest amount of time to wait between retries. No guarantees that this will - * be respected on API >= 26. - */ - public @NonNull Builder setMaxBackoff(long maxBackoff) { - this.maxBackoff = maxBackoff; - return this; - } - - /** - * Specify the maximum number of instances you'd want of this job at any given time. If - * enqueueing this job would put it over that limit, it will be ignored. - * - * Duplicates are determined by two jobs having the same {@link Job#getFactoryKey()}. - * - * This property is ignored if the job is submitted as part of a {@link JobManager.Chain}. - * - * Defaults to {@link #UNLIMITED}. - */ - public @NonNull Builder setMaxInstances(int maxInstances) { - this.maxInstances = maxInstances; - return this; - } - - /** - * Specify a string representing a queue. All jobs within the same queue are run in a - * serialized fashion -- one after the other, in order of insertion. Failure of a job earlier - * in the queue has no impact on the execution of jobs later in the queue. - */ - public @NonNull Builder setQueue(@Nullable String queue) { - this.queue = queue; - return this; - } - - /** - * Add a constraint via the key that was used to register its factory in - * {@link JobManager.Configuration)}; - */ - public @NonNull Builder addConstraint(@NonNull String constraintKey) { - constraintKeys.add(constraintKey); - return this; - } - - /** - * Set constraints via the key that was used to register its factory in - * {@link JobManager.Configuration)}; - */ - public @NonNull Builder setConstraints(@NonNull List constraintKeys) { - this.constraintKeys.clear(); - this.constraintKeys.addAll(constraintKeys); - return this; - } - - public @NonNull Parameters build() { - return new Parameters(createTime, lifespan, maxAttempts, maxBackoff, maxInstances, queue, constraintKeys); - } - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobController.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobController.java deleted file mode 100644 index 33345a03e1..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobController.java +++ /dev/null @@ -1,354 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import android.app.Application; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.WorkerThread; - -import com.annimon.stream.Stream; - -import org.session.libsession.messaging.utilities.Data; -import org.session.libsession.utilities.Debouncer; -import org.session.libsignal.utilities.Log; -import org.thoughtcrime.securesms.jobmanager.persistence.ConstraintSpec; -import org.thoughtcrime.securesms.jobmanager.persistence.DependencySpec; -import org.thoughtcrime.securesms.jobmanager.persistence.FullSpec; -import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec; -import org.thoughtcrime.securesms.jobmanager.persistence.JobStorage; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.UUID; - -/** - * Manages the queue of jobs. This is the only class that should write to {@link JobStorage} to - * ensure consistency. - */ -class JobController { - - private static final String TAG = JobController.class.getSimpleName(); - - private final Application application; - private final JobStorage jobStorage; - private final JobInstantiator jobInstantiator; - private final ConstraintInstantiator constraintInstantiator; - private final Data.Serializer dataSerializer; - private final Scheduler scheduler; - private final Debouncer debouncer; - private final Callback callback; - private final Set runningJobs; - - JobController(@NonNull Application application, - @NonNull JobStorage jobStorage, - @NonNull JobInstantiator jobInstantiator, - @NonNull ConstraintInstantiator constraintInstantiator, - @NonNull Data.Serializer dataSerializer, - @NonNull Scheduler scheduler, - @NonNull Debouncer debouncer, - @NonNull Callback callback) - { - this.application = application; - this.jobStorage = jobStorage; - this.jobInstantiator = jobInstantiator; - this.constraintInstantiator = constraintInstantiator; - this.dataSerializer = dataSerializer; - this.scheduler = scheduler; - this.debouncer = debouncer; - this.callback = callback; - this.runningJobs = new HashSet<>(); - } - - @WorkerThread - synchronized void init() { - jobStorage.init(); - jobStorage.updateAllJobsToBePending(); - notifyAll(); - } - - synchronized void wakeUp() { - notifyAll(); - } - - @WorkerThread - synchronized void submitNewJobChain(@NonNull List> chain) { - chain = Stream.of(chain).filterNot(List::isEmpty).toList(); - - if (chain.isEmpty()) { - Log.w(TAG, "Tried to submit an empty job chain. Skipping."); - return; - } - - if (chainExceedsMaximumInstances(chain)) { - Job solo = chain.get(0).get(0); - Log.w(TAG, JobLogger.format(solo, "Already at the max instance count of " + solo.getParameters().getMaxInstances() + ". Skipping.")); - return; - } - - insertJobChain(chain); - scheduleJobs(chain.get(0)); - triggerOnSubmit(chain); - notifyAll(); - } - - @WorkerThread - synchronized void onRetry(@NonNull Job job) { - int nextRunAttempt = job.getRunAttempt() + 1; - long nextRunAttemptTime = calculateNextRunAttemptTime(System.currentTimeMillis(), nextRunAttempt, job.getParameters().getMaxBackoff()); - - jobStorage.updateJobAfterRetry(job.getId(), false, nextRunAttempt, nextRunAttemptTime); - - List constraints = Stream.of(jobStorage.getConstraintSpecs(job.getId())) - .map(ConstraintSpec::getFactoryKey) - .map(constraintInstantiator::instantiate) - .toList(); - - - long delay = Math.max(0, nextRunAttemptTime - System.currentTimeMillis()); - - Log.i(TAG, JobLogger.format(job, "Scheduling a retry in " + delay + " ms.")); - scheduler.schedule(delay, constraints); - - notifyAll(); - } - - synchronized void onJobFinished(@NonNull Job job) { - runningJobs.remove(job.getId()); - } - - @WorkerThread - synchronized void onSuccess(@NonNull Job job) { - jobStorage.deleteJob(job.getId()); - notifyAll(); - } - - /** - * @return The list of all dependent jobs that should also be failed. - */ - @WorkerThread - synchronized @NonNull List onFailure(@NonNull Job job) { - List dependents = Stream.of(jobStorage.getDependencySpecsThatDependOnJob(job.getId())) - .map(DependencySpec::getJobId) - .map(jobStorage::getJobSpec) - .withoutNulls() - .map(jobSpec -> { - List constraintSpecs = jobStorage.getConstraintSpecs(jobSpec.getId()); - return createJob(jobSpec, constraintSpecs); - }) - .toList(); - - List all = new ArrayList<>(dependents.size() + 1); - all.add(job); - all.addAll(dependents); - - jobStorage.deleteJobs(Stream.of(all).map(Job::getId).toList()); - - return dependents; - } - - /** - * Retrieves the next job that is eligible for execution. To be 'eligible' means that the job: - * - Has no dependencies - * - Has no unmet constraints - * - * This method will block until a job is available. - * When the job returned from this method has been run, you must call {@link #onJobFinished(Job)}. - */ - @WorkerThread - synchronized @NonNull Job pullNextEligibleJobForExecution() { - try { - Job job; - - while ((job = getNextEligibleJobForExecution()) == null) { - if (runningJobs.isEmpty()) { - debouncer.publish(callback::onEmpty); - } - - wait(); - } - - jobStorage.updateJobRunningState(job.getId(), true); - runningJobs.add(job.getId()); - - return job; - } catch (InterruptedException e) { - Log.e(TAG, "Interrupted."); - throw new AssertionError(e); - } - } - - /** - * Retrieves a string representing the state of the job queue. Intended for debugging. - */ - @WorkerThread - synchronized @NonNull String getDebugInfo() { - List jobs = jobStorage.getAllJobSpecs(); - List constraints = jobStorage.getAllConstraintSpecs(); - List dependencies = jobStorage.getAllDependencySpecs(); - - StringBuilder info = new StringBuilder(); - - info.append("-- Jobs\n"); - if (!jobs.isEmpty()) { - Stream.of(jobs).forEach(j -> info.append(j.toString()).append('\n')); - } else { - info.append("None\n"); - } - - info.append("\n-- Constraints\n"); - if (!constraints.isEmpty()) { - Stream.of(constraints).forEach(c -> info.append(c.toString()).append('\n')); - } else { - info.append("None\n"); - } - - info.append("\n-- Dependencies\n"); - if (!dependencies.isEmpty()) { - Stream.of(dependencies).forEach(d -> info.append(d.toString()).append('\n')); - } else { - info.append("None\n"); - } - - return info.toString(); - } - - @WorkerThread - private boolean chainExceedsMaximumInstances(@NonNull List> chain) { - if (chain.size() == 1 && chain.get(0).size() == 1) { - Job solo = chain.get(0).get(0); - - if (solo.getParameters().getMaxInstances() != Job.Parameters.UNLIMITED && - jobStorage.getJobInstanceCount(solo.getFactoryKey()) >= solo.getParameters().getMaxInstances()) - { - return true; - } - } - return false; - } - - @WorkerThread - private void triggerOnSubmit(@NonNull List> chain) { - Stream.of(chain) - .forEach(list -> Stream.of(list).forEach(job -> { - job.setContext(application); - job.onSubmit(); - })); - } - - @WorkerThread - private void insertJobChain(@NonNull List> chain) { - List fullSpecs = new LinkedList<>(); - List dependsOn = Collections.emptyList(); - - for (List jobList : chain) { - for (Job job : jobList) { - fullSpecs.add(buildFullSpec(job, dependsOn)); - } - dependsOn = jobList; - } - - jobStorage.insertJobs(fullSpecs); - } - - @WorkerThread - private @NonNull FullSpec buildFullSpec(@NonNull Job job, @NonNull List dependsOn) { - String id = UUID.randomUUID().toString(); - - job.setId(id); - job.setRunAttempt(0); - - JobSpec jobSpec = new JobSpec(job.getId(), - job.getFactoryKey(), - job.getParameters().getQueue(), - job.getParameters().getCreateTime(), - job.getNextRunAttemptTime(), - job.getRunAttempt(), - job.getParameters().getMaxAttempts(), - job.getParameters().getMaxBackoff(), - job.getParameters().getLifespan(), - job.getParameters().getMaxInstances(), - dataSerializer.serialize(job.serialize()), - false); - - List constraintSpecs = Stream.of(job.getParameters().getConstraintKeys()) - .map(key -> new ConstraintSpec(jobSpec.getId(), key)) - .toList(); - - List dependencySpecs = Stream.of(dependsOn) - .map(depends -> new DependencySpec(job.getId(), depends.getId())) - .toList(); - - return new FullSpec(jobSpec, constraintSpecs, dependencySpecs); - } - - @WorkerThread - private void scheduleJobs(@NonNull List jobs) { - for (Job job : jobs) { - List constraints = Stream.of(job.getParameters().getConstraintKeys()) - .map(key -> new ConstraintSpec(job.getId(), key)) - .map(ConstraintSpec::getFactoryKey) - .map(constraintInstantiator::instantiate) - .toList(); - - scheduler.schedule(0, constraints); - } - } - - @WorkerThread - private @Nullable Job getNextEligibleJobForExecution() { - List jobSpecs = jobStorage.getPendingJobsWithNoDependenciesInCreatedOrder(System.currentTimeMillis()); - - for (JobSpec jobSpec : jobSpecs) { - List constraintSpecs = jobStorage.getConstraintSpecs(jobSpec.getId()); - List constraints = Stream.of(constraintSpecs) - .map(ConstraintSpec::getFactoryKey) - .map(constraintInstantiator::instantiate) - .toList(); - - if (Stream.of(constraints).allMatch(Constraint::isMet)) { - return createJob(jobSpec, constraintSpecs); - } - } - - return null; - } - - private @NonNull Job createJob(@NonNull JobSpec jobSpec, @NonNull List constraintSpecs) { - Job.Parameters parameters = buildJobParameters(jobSpec, constraintSpecs); - Data data = dataSerializer.deserialize(jobSpec.getSerializedData()); - Job job = jobInstantiator.instantiate(jobSpec.getFactoryKey(), parameters, data); - - job.setId(jobSpec.getId()); - job.setRunAttempt(jobSpec.getRunAttempt()); - job.setNextRunAttemptTime(jobSpec.getNextRunAttemptTime()); - job.setContext(application); - - return job; - } - - private @NonNull Job.Parameters buildJobParameters(@NonNull JobSpec jobSpec, @NonNull List constraintSpecs) { - return new Job.Parameters.Builder() - .setCreateTime(jobSpec.getCreateTime()) - .setLifespan(jobSpec.getLifespan()) - .setMaxAttempts(jobSpec.getMaxAttempts()) - .setQueue(jobSpec.getQueueKey()) - .setConstraints(Stream.of(constraintSpecs).map(ConstraintSpec::getFactoryKey).toList()) - .build(); - } - - private long calculateNextRunAttemptTime(long currentTime, int nextAttempt, long maxBackoff) { - int boundedAttempt = Math.min(nextAttempt, 30); - long exponentialBackoff = (long) Math.pow(2, boundedAttempt) * 1000; - long actualBackoff = Math.min(exponentialBackoff, maxBackoff); - - return currentTime + actualBackoff; - } - - interface Callback { - void onEmpty(); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobInstantiator.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobInstantiator.java deleted file mode 100644 index 6d1527d131..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobInstantiator.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import androidx.annotation.NonNull; - -import org.session.libsession.messaging.utilities.Data; - -import java.util.HashMap; -import java.util.Map; - -class JobInstantiator { - - private final Map jobFactories; - - JobInstantiator(@NonNull Map jobFactories) { - this.jobFactories = new HashMap<>(jobFactories); - } - - public @NonNull Job instantiate(@NonNull String jobFactoryKey, @NonNull Job.Parameters parameters, @NonNull Data data) { - if (jobFactories.containsKey(jobFactoryKey)) { - return jobFactories.get(jobFactoryKey).create(parameters, data); - } else { - throw new IllegalStateException("Tried to instantiate a job with key '" + jobFactoryKey + "', but no matching factory was found."); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobLogger.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobLogger.java deleted file mode 100644 index c35f6dc1ac..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobLogger.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import androidx.annotation.NonNull; -import android.text.TextUtils; - -public class JobLogger { - - public static String format(@NonNull Job job, @NonNull String event) { - return format(job, "", event); - } - - public static String format(@NonNull Job job, @NonNull String extraTag, @NonNull String event) { - String id = job.getId(); - String tag = TextUtils.isEmpty(extraTag) ? "" : "[" + extraTag + "]"; - long timeSinceSubmission = System.currentTimeMillis() - job.getParameters().getCreateTime(); - int runAttempt = job.getRunAttempt() + 1; - String maxAttempts = job.getParameters().getMaxAttempts() == Job.Parameters.UNLIMITED ? "Unlimited" - : String.valueOf(job.getParameters().getMaxAttempts()); - String lifespan = job.getParameters().getLifespan() == Job.Parameters.IMMORTAL ? "Immortal" - : String.valueOf(job.getParameters().getLifespan()) + " ms"; - return String.format("[%s][%s]%s %s (Time Since Submission: %d ms, Lifespan: %s, Run Attempt: %d/%s)", - id, job.getClass().getSimpleName(), tag, event, timeSinceSubmission, lifespan, runAttempt, maxAttempts); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java deleted file mode 100644 index 5906afd292..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java +++ /dev/null @@ -1,310 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import android.app.Application; -import android.content.Intent; -import android.os.Build; - -import androidx.annotation.NonNull; - -import org.session.libsession.messaging.utilities.Data; -import org.session.libsession.utilities.Debouncer; -import org.session.libsignal.utilities.Log; -import org.thoughtcrime.securesms.jobmanager.impl.DefaultExecutorFactory; -import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer; -import org.thoughtcrime.securesms.jobmanager.persistence.JobStorage; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; - -/** - * Allows the scheduling of durable jobs that will be run as early as possible. - */ -public class JobManager implements ConstraintObserver.Notifier { - - private static final String TAG = JobManager.class.getSimpleName(); - - private final ExecutorService executor; - private final JobController jobController; - private final JobRunner[] jobRunners; - - private final Set emptyQueueListeners = new CopyOnWriteArraySet<>(); - - public JobManager(@NonNull Application application, @NonNull Configuration configuration) { - this.executor = configuration.getExecutorFactory().newSingleThreadExecutor("JobManager"); - this.jobRunners = new JobRunner[configuration.getJobThreadCount()]; - this.jobController = new JobController(application, - configuration.getJobStorage(), - configuration.getJobInstantiator(), - configuration.getConstraintFactories(), - configuration.getDataSerializer(), - Build.VERSION.SDK_INT < 26 ? new AlarmManagerScheduler(application) - : new CompositeScheduler(new InAppScheduler(this), new JobSchedulerScheduler(application)), - new Debouncer(500), - this::onEmptyQueue); - - executor.execute(() -> { - jobController.init(); - - for (int i = 0; i < jobRunners.length; i++) { - jobRunners[i] = new JobRunner(application, i + 1, jobController); - jobRunners[i].start(); - } - - for (ConstraintObserver constraintObserver : configuration.getConstraintObservers()) { - constraintObserver.register(this); - } - - if (Build.VERSION.SDK_INT < 26) { - application.startService(new Intent(application, KeepAliveService.class)); - } - - wakeUp(); - }); - } - - /** - * Enqueues a single job to be run. - */ - public void add(@NonNull Job job) { - new Chain(this, Collections.singletonList(job)).enqueue(); - } - - /** - * Begins the creation of a job chain with a single job. - * @see Chain - */ - public Chain startChain(@NonNull Job job) { - return new Chain(this, Collections.singletonList(job)); - } - - /** - * Begins the creation of a job chain with a set of jobs that can be run in parallel. - * @see Chain - */ - public Chain startChain(@NonNull List jobs) { - return new Chain(this, jobs); - } - - /** - * Retrieves a string representing the state of the job queue. Intended for debugging. - */ - public @NonNull String getDebugInfo() { - Future result = executor.submit(jobController::getDebugInfo); - try { - return result.get(); - } catch (ExecutionException | InterruptedException e) { - Log.w(TAG, "Failed to retrieve Job info.", e); - return "Failed to retrieve Job info."; - } - } - - /** - * Adds a listener to that will be notified when the job queue has been drained. - */ - void addOnEmptyQueueListener(@NonNull EmptyQueueListener listener) { - executor.execute(() -> { - emptyQueueListeners.add(listener); - }); - } - - /** - * Removes a listener that was added via {@link #addOnEmptyQueueListener(EmptyQueueListener)}. - */ - void removeOnEmptyQueueListener(@NonNull EmptyQueueListener listener) { - executor.execute(() -> { - emptyQueueListeners.remove(listener); - }); - } - - @Override - public void onConstraintMet(@NonNull String reason) { - Log.i(TAG, "onConstraintMet(" + reason + ")"); - wakeUp(); - } - - /** - * Pokes the system to take another pass at the job queue. - */ - void wakeUp() { - executor.execute(jobController::wakeUp); - } - - private void enqueueChain(@NonNull Chain chain) { - executor.execute(() -> { - jobController.submitNewJobChain(chain.getJobListChain()); - wakeUp(); - }); - } - - private void onEmptyQueue() { - executor.execute(() -> { - for (EmptyQueueListener listener : emptyQueueListeners) { - listener.onQueueEmpty(); - } - }); - } - - public interface EmptyQueueListener { - void onQueueEmpty(); - } - - /** - * Allows enqueuing work that depends on each other. Jobs that appear later in the chain will - * only run after all jobs earlier in the chain have been completed. If a job fails, all jobs - * that occur later in the chain will also be failed. - */ - public static class Chain { - - private final JobManager jobManager; - private final List> jobs; - - private Chain(@NonNull JobManager jobManager, @NonNull List jobs) { - this.jobManager = jobManager; - this.jobs = new LinkedList<>(); - - this.jobs.add(new ArrayList<>(jobs)); - } - - public Chain then(@NonNull Job job) { - return then(Collections.singletonList(job)); - } - - public Chain then(@NonNull List jobs) { - if (!jobs.isEmpty()) { - this.jobs.add(new ArrayList<>(jobs)); - } - return this; - } - - public void enqueue() { - jobManager.enqueueChain(this); - } - - private List> getJobListChain() { - return jobs; - } - } - - public static class Configuration { - - private final ExecutorFactory executorFactory; - private final int jobThreadCount; - private final JobInstantiator jobInstantiator; - private final ConstraintInstantiator constraintInstantiator; - private final List constraintObservers; - private final Data.Serializer dataSerializer; - private final JobStorage jobStorage; - - private Configuration(int jobThreadCount, - @NonNull ExecutorFactory executorFactory, - @NonNull JobInstantiator jobInstantiator, - @NonNull ConstraintInstantiator constraintInstantiator, - @NonNull List constraintObservers, - @NonNull Data.Serializer dataSerializer, - @NonNull JobStorage jobStorage) - { - this.executorFactory = executorFactory; - this.jobThreadCount = jobThreadCount; - this.jobInstantiator = jobInstantiator; - this.constraintInstantiator = constraintInstantiator; - this.constraintObservers = constraintObservers; - this.dataSerializer = dataSerializer; - this.jobStorage = jobStorage; - } - - int getJobThreadCount() { - return jobThreadCount; - } - - @NonNull ExecutorFactory getExecutorFactory() { - return executorFactory; - } - - @NonNull JobInstantiator getJobInstantiator() { - return jobInstantiator; - } - - @NonNull - ConstraintInstantiator getConstraintFactories() { - return constraintInstantiator; - } - - @NonNull List getConstraintObservers() { - return constraintObservers; - } - - @NonNull Data.Serializer getDataSerializer() { - return dataSerializer; - } - - @NonNull JobStorage getJobStorage() { - return jobStorage; - } - - - public static class Builder { - - private ExecutorFactory executorFactory = new DefaultExecutorFactory(); - private int jobThreadCount = 1; - private Map jobFactories = new HashMap<>(); - private Map constraintFactories = new HashMap<>(); - private List constraintObservers = new ArrayList<>(); - private Data.Serializer dataSerializer = new JsonDataSerializer(); - private JobStorage jobStorage = null; - - public @NonNull Builder setJobThreadCount(int jobThreadCount) { - this.jobThreadCount = jobThreadCount; - return this; - } - - public @NonNull Builder setExecutorFactory(@NonNull ExecutorFactory executorFactory) { - this.executorFactory = executorFactory; - return this; - } - - public @NonNull Builder setJobFactories(@NonNull Map jobFactories) { - this.jobFactories = jobFactories; - return this; - } - - public @NonNull Builder setConstraintFactories(@NonNull Map constraintFactories) { - this.constraintFactories = constraintFactories; - return this; - } - - public @NonNull Builder setConstraintObservers(@NonNull List constraintObservers) { - this.constraintObservers = constraintObservers; - return this; - } - - public @NonNull Builder setDataSerializer(@NonNull Data.Serializer dataSerializer) { - this.dataSerializer = dataSerializer; - return this; - } - - public @NonNull Builder setJobStorage(@NonNull JobStorage jobStorage) { - this.jobStorage = jobStorage; - return this; - } - - public @NonNull Configuration build() { - return new Configuration(jobThreadCount, - executorFactory, - new JobInstantiator(jobFactories), - new ConstraintInstantiator(constraintFactories), - new ArrayList<>(constraintObservers), - dataSerializer, - jobStorage); - } - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobRunner.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobRunner.java deleted file mode 100644 index 6eadf0fd5d..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobRunner.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import android.app.Application; -import android.os.PowerManager; -import androidx.annotation.NonNull; - -import com.annimon.stream.Stream; - -import org.session.libsignal.utilities.Log; -import org.thoughtcrime.securesms.util.WakeLockUtil; - -import java.util.List; -import java.util.concurrent.TimeUnit; - -class JobRunner extends Thread { - - private static final String TAG = JobRunner.class.getSimpleName(); - - private static long WAKE_LOCK_TIMEOUT = TimeUnit.MINUTES.toMillis(10); - - private final Application application; - private final int id; - private final JobController jobController; - - JobRunner(@NonNull Application application, int id, @NonNull JobController jobController) { - super("JobRunner-" + id); - - this.application = application; - this.id = id; - this.jobController = jobController; - } - - @Override - public synchronized void run() { - while (true) { - Job job = jobController.pullNextEligibleJobForExecution(); - Job.Result result = run(job); - - jobController.onJobFinished(job); - - switch (result) { - case SUCCESS: - jobController.onSuccess(job); - break; - case RETRY: - jobController.onRetry(job); - job.onRetry(); - break; - case FAILURE: - List dependents = jobController.onFailure(job); - job.onCanceled(); - Stream.of(dependents).forEach(Job::onCanceled); - break; - } - } - } - - private Job.Result run(@NonNull Job job) { - Log.i(TAG, JobLogger.format(job, String.valueOf(id), "Running job.")); - - if (isJobExpired(job)) { - Log.w(TAG, JobLogger.format(job, String.valueOf(id), "Failing after surpassing its lifespan.")); - return Job.Result.FAILURE; - } - - Job.Result result = null; - PowerManager.WakeLock wakeLock = null; - - try { - wakeLock = WakeLockUtil.acquire(application, PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TIMEOUT, job.getId()); - result = job.run(); - } catch (Exception e) { - Log.w(TAG, JobLogger.format(job, String.valueOf(id), "Failing due to an unexpected exception."), e); - return Job.Result.FAILURE; - } finally { - if (wakeLock != null) { - WakeLockUtil.release(wakeLock, job.getId()); - } - } - - printResult(job, result); - - if (result == Job.Result.RETRY && job.getRunAttempt() + 1 >= job.getParameters().getMaxAttempts() && - job.getParameters().getMaxAttempts() != Job.Parameters.UNLIMITED) - { - Log.w(TAG, JobLogger.format(job, String.valueOf(id), "Failing after surpassing its max number of attempts.")); - return Job.Result.FAILURE; - } - - return result; - } - - private boolean isJobExpired(@NonNull Job job) { - long expirationTime = job.getParameters().getCreateTime() + job.getParameters().getLifespan(); - - if (expirationTime < 0) { - expirationTime = Long.MAX_VALUE; - } - - return job.getParameters().getLifespan() != Job.Parameters.IMMORTAL && expirationTime <= System.currentTimeMillis(); - } - - private void printResult(@NonNull Job job, @NonNull Job.Result result) { - if (result == Job.Result.FAILURE) { - Log.w(TAG, JobLogger.format(job, String.valueOf(id), "Job failed.")); - } else { - Log.i(TAG, JobLogger.format(job, String.valueOf(id), "Job finished with result: " + result)); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobSchedulerScheduler.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobSchedulerScheduler.java deleted file mode 100644 index 40acbf520b..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobSchedulerScheduler.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import android.app.Application; -import android.app.job.JobInfo; -import android.app.job.JobParameters; -import android.app.job.JobScheduler; -import android.app.job.JobService; -import android.content.ComponentName; -import android.content.Context; -import android.content.SharedPreferences; -import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; - -import org.thoughtcrime.securesms.ApplicationContext; -import org.session.libsignal.utilities.Log; - -import java.util.List; - -@RequiresApi(26) -public class JobSchedulerScheduler implements Scheduler { - - private static final String TAG = JobSchedulerScheduler.class.getSimpleName(); - - private static final String PREF_NAME = "JobSchedulerScheduler_prefs"; - private static final String PREF_NEXT_ID = "pref_next_id"; - - private static final int MAX_ID = 75; - - private final Application application; - - JobSchedulerScheduler(@NonNull Application application) { - this.application = application; - } - - @RequiresApi(26) - @Override - public void schedule(long delay, @NonNull List constraints) { - JobInfo.Builder jobInfoBuilder = new JobInfo.Builder(getNextId(), new ComponentName(application, SystemService.class)) - .setMinimumLatency(delay) - .setPersisted(true); - - for (Constraint constraint : constraints) { - constraint.applyToJobInfo(jobInfoBuilder); - } - - Log.i(TAG, "Scheduling a run in " + delay + " ms."); - JobScheduler jobScheduler = application.getSystemService(JobScheduler.class); - jobScheduler.schedule(jobInfoBuilder.build()); - } - - private int getNextId() { - SharedPreferences prefs = application.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); - int returnedId = prefs.getInt(PREF_NEXT_ID, 0); - int nextId = returnedId + 1 > MAX_ID ? 0 : returnedId + 1; - - prefs.edit().putInt(PREF_NEXT_ID, nextId).apply(); - - return returnedId; - } - - @RequiresApi(api = 26) - public static class SystemService extends JobService { - - @Override - public boolean onStartJob(JobParameters params) { - Log.d(TAG, "onStartJob()"); - - JobManager jobManager = ApplicationContext.getInstance(getApplicationContext()).getJobManager(); - - jobManager.addOnEmptyQueueListener(new JobManager.EmptyQueueListener() { - @Override - public void onQueueEmpty() { - jobManager.removeOnEmptyQueueListener(this); - jobFinished(params, false); - Log.d(TAG, "jobFinished()"); - } - }); - - jobManager.wakeUp(); - - return true; - } - - @Override - public boolean onStopJob(JobParameters params) { - Log.d(TAG, "onStopJob()"); - return false; - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Scheduler.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Scheduler.java deleted file mode 100644 index 194acd39b2..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/Scheduler.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager; - -import androidx.annotation.NonNull; - -import java.util.List; - -public interface Scheduler { - void schedule(long delay, @NonNull List constraints); -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraint.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraint.java deleted file mode 100644 index 6d6fc0499f..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraint.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.impl; - -import android.app.Application; -import android.app.job.JobInfo; -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.jobmanager.Constraint; -import org.thoughtcrime.securesms.sms.TelephonyServiceState; - -public class CellServiceConstraint implements Constraint { - - public static final String KEY = "CellServiceConstraint"; - - private final Application application; - - public CellServiceConstraint(@NonNull Application application) { - this.application = application; - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - public boolean isMet() { - TelephonyServiceState telephonyServiceState = new TelephonyServiceState(); - return telephonyServiceState.isConnected(application); - } - - @Override - public void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder) { - } - - public static final class Factory implements Constraint.Factory { - - private final Application application; - - public Factory(@NonNull Application application) { - this.application = application; - } - - @Override - public CellServiceConstraint create() { - return new CellServiceConstraint(application); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraintObserver.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraintObserver.java deleted file mode 100644 index fd0971dc57..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/CellServiceConstraintObserver.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.impl; - -import android.app.Application; -import android.content.Context; -import androidx.annotation.NonNull; -import android.telephony.PhoneStateListener; -import android.telephony.ServiceState; -import android.telephony.TelephonyManager; - -import org.thoughtcrime.securesms.jobmanager.ConstraintObserver; - -public class CellServiceConstraintObserver implements ConstraintObserver { - - private static final String REASON = CellServiceConstraintObserver.class.getSimpleName(); - - private Notifier notifier; - - public CellServiceConstraintObserver(@NonNull Application application) { - TelephonyManager telephonyManager = (TelephonyManager) application.getSystemService(Context.TELEPHONY_SERVICE); - ServiceStateListener serviceStateListener = new ServiceStateListener(); - - telephonyManager.listen(serviceStateListener, PhoneStateListener.LISTEN_SERVICE_STATE); - } - - @Override - public void register(@NonNull Notifier notifier) { - this.notifier = notifier; - } - - private class ServiceStateListener extends PhoneStateListener { - @Override - public void onServiceStateChanged(ServiceState serviceState) { - if (serviceState.getState() == ServiceState.STATE_IN_SERVICE && notifier != null) { - notifier.onConstraintMet(REASON); - } - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/DefaultExecutorFactory.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/DefaultExecutorFactory.java deleted file mode 100644 index a9d4591009..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/DefaultExecutorFactory.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.impl; - -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.jobmanager.ExecutorFactory; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -public class DefaultExecutorFactory implements ExecutorFactory { - @Override - public @NonNull ExecutorService newSingleThreadExecutor(@NonNull String name) { - return Executors.newSingleThreadExecutor(r -> new Thread(r, name)); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkConstraintObserver.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkConstraintObserver.java deleted file mode 100644 index ef4a61c7c5..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkConstraintObserver.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.impl; - -import android.app.Application; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.ConnectivityManager; -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.jobmanager.ConstraintObserver; - -public class NetworkConstraintObserver implements ConstraintObserver { - - private static final String REASON = NetworkConstraintObserver.class.getSimpleName(); - - private final Application application; - - public NetworkConstraintObserver(Application application) { - this.application = application; - } - - @Override - public void register(@NonNull Notifier notifier) { - application.registerReceiver(new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - NetworkConstraint constraint = new NetworkConstraint.Factory(application).create(); - - if (constraint.isMet()) { - notifier.onConstraintMet(REASON); - } - } - }, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkOrCellServiceConstraint.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkOrCellServiceConstraint.java deleted file mode 100644 index c17931f977..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/NetworkOrCellServiceConstraint.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.impl; - -import android.app.Application; -import android.app.job.JobInfo; -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.jobmanager.Constraint; - -public class NetworkOrCellServiceConstraint implements Constraint { - - public static final String KEY = "NetworkOrCellServiceConstraint"; - - private final NetworkConstraint networkConstraint; - private final CellServiceConstraint serviceConstraint; - - public NetworkOrCellServiceConstraint(@NonNull Application application) { - networkConstraint = new NetworkConstraint.Factory(application).create(); - serviceConstraint = new CellServiceConstraint.Factory(application).create(); - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - public boolean isMet() { - return networkConstraint.isMet() || serviceConstraint.isMet(); - } - - @Override - public void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder) { - } - - public static class Factory implements Constraint.Factory { - - private final Application application; - - public Factory(@NonNull Application application) { - this.application = application; - } - - @Override - public NetworkOrCellServiceConstraint create() { - return new NetworkOrCellServiceConstraint(application); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraint.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraint.java deleted file mode 100644 index 32fa84b6f5..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraint.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.impl; - -import android.app.Application; -import android.app.job.JobInfo; -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.jobmanager.Constraint; -import org.session.libsession.utilities.TextSecurePreferences; - -public class SqlCipherMigrationConstraint implements Constraint { - - public static final String KEY = "SqlCipherMigrationConstraint"; - - private final Application application; - - private SqlCipherMigrationConstraint(@NonNull Application application) { - this.application = application; - } - - @Override - public boolean isMet() { - return !TextSecurePreferences.getNeedsSqlCipherMigration(application); - } - - @NonNull - @Override - public String getFactoryKey() { - return KEY; - } - - @Override - public void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder) { - } - - public static final class Factory implements Constraint.Factory { - - private final Application application; - - public Factory(@NonNull Application application) { - this.application = application; - } - - @Override - public SqlCipherMigrationConstraint create() { - return new SqlCipherMigrationConstraint(application); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraintObserver.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraintObserver.java deleted file mode 100644 index 0c9225434d..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/impl/SqlCipherMigrationConstraintObserver.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.impl; - -import androidx.annotation.NonNull; - -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; -import org.thoughtcrime.securesms.jobmanager.ConstraintObserver; - -public class SqlCipherMigrationConstraintObserver implements ConstraintObserver { - - private static final String REASON = SqlCipherMigrationConstraintObserver.class.getSimpleName(); - - private Notifier notifier; - - public SqlCipherMigrationConstraintObserver() { - EventBus.getDefault().register(this); - } - - @Override - public void register(@NonNull Notifier notifier) { - this.notifier = notifier; - } - - @Subscribe(threadMode = ThreadMode.MAIN) - public void onEvent(SqlCipherNeedsMigrationEvent event) { - if (notifier != null) notifier.onConstraintMet(REASON); - } - - public static class SqlCipherNeedsMigrationEvent { - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/ConstraintSpec.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/ConstraintSpec.java deleted file mode 100644 index 1dab10ae56..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/ConstraintSpec.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.persistence; - -import androidx.annotation.NonNull; - -import java.util.Objects; - -public final class ConstraintSpec { - - private final String jobSpecId; - private final String factoryKey; - - public ConstraintSpec(@NonNull String jobSpecId, @NonNull String factoryKey) { - this.jobSpecId = jobSpecId; - this.factoryKey = factoryKey; - } - - public String getJobSpecId() { - return jobSpecId; - } - - public String getFactoryKey() { - return factoryKey; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ConstraintSpec that = (ConstraintSpec) o; - return Objects.equals(jobSpecId, that.jobSpecId) && - Objects.equals(factoryKey, that.factoryKey); - } - - @Override - public int hashCode() { - return Objects.hash(jobSpecId, factoryKey); - } - - @Override - public @NonNull String toString() { - return String.format("jobSpecId: %s | factoryKey: %s", jobSpecId, factoryKey); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/DependencySpec.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/DependencySpec.java deleted file mode 100644 index 2faea0485b..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/DependencySpec.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.persistence; - -import androidx.annotation.NonNull; - -import java.util.Objects; - -public final class DependencySpec { - - private final String jobId; - private final String dependsOnJobId; - - public DependencySpec(@NonNull String jobId, @NonNull String dependsOnJobId) { - this.jobId = jobId; - this.dependsOnJobId = dependsOnJobId; - } - - public @NonNull String getJobId() { - return jobId; - } - - public @NonNull String getDependsOnJobId() { - return dependsOnJobId; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - DependencySpec that = (DependencySpec) o; - return Objects.equals(jobId, that.jobId) && - Objects.equals(dependsOnJobId, that.dependsOnJobId); - } - - @Override - public int hashCode() { - return Objects.hash(jobId, dependsOnJobId); - } - - @Override - public @NonNull String toString() { - return String.format("jobSpecId: %s | dependsOnJobSpecId: %s", jobId, dependsOnJobId); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/FullSpec.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/FullSpec.java deleted file mode 100644 index f93c0e64bd..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/FullSpec.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.persistence; - -import androidx.annotation.NonNull; - -import java.util.List; -import java.util.Objects; - -public final class FullSpec { - - private final JobSpec jobSpec; - private final List constraintSpecs; - private final List dependencySpecs; - - public FullSpec(@NonNull JobSpec jobSpec, - @NonNull List constraintSpecs, - @NonNull List dependencySpecs) - { - this.jobSpec = jobSpec; - this.constraintSpecs = constraintSpecs; - this.dependencySpecs = dependencySpecs; - } - - public @NonNull JobSpec getJobSpec() { - return jobSpec; - } - - public @NonNull List getConstraintSpecs() { - return constraintSpecs; - } - - public @NonNull List getDependencySpecs() { - return dependencySpecs; - } - - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - FullSpec fullSpec = (FullSpec) o; - return Objects.equals(jobSpec, fullSpec.jobSpec) && - Objects.equals(constraintSpecs, fullSpec.constraintSpecs) && - Objects.equals(dependencySpecs, fullSpec.dependencySpecs); - } - - @Override - public int hashCode() { - return Objects.hash(jobSpec, constraintSpecs, dependencySpecs); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/JobSpec.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/JobSpec.java deleted file mode 100644 index d5f5cd5b3e..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/JobSpec.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.persistence; - -import android.annotation.SuppressLint; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.util.Objects; - -public final class JobSpec { - - private final String id; - private final String factoryKey; - private final String queueKey; - private final long createTime; - private final long nextRunAttemptTime; - private final int runAttempt; - private final int maxAttempts; - private final long maxBackoff; - private final long lifespan; - private final int maxInstances; - private final String serializedData; - private final boolean isRunning; - - public JobSpec(@NonNull String id, - @NonNull String factoryKey, - @Nullable String queueKey, - long createTime, - long nextRunAttemptTime, - int runAttempt, - int maxAttempts, - long maxBackoff, - long lifespan, - int maxInstances, - @NonNull String serializedData, - boolean isRunning) - { - this.id = id; - this.factoryKey = factoryKey; - this.queueKey = queueKey; - this.createTime = createTime; - this.nextRunAttemptTime = nextRunAttemptTime; - this.maxBackoff = maxBackoff; - this.runAttempt = runAttempt; - this.maxAttempts = maxAttempts; - this.lifespan = lifespan; - this.maxInstances = maxInstances; - this.serializedData = serializedData; - this.isRunning = isRunning; - } - - public @NonNull String getId() { - return id; - } - - public @NonNull String getFactoryKey() { - return factoryKey; - } - - public @Nullable String getQueueKey() { - return queueKey; - } - - public long getCreateTime() { - return createTime; - } - - public long getNextRunAttemptTime() { - return nextRunAttemptTime; - } - - public int getRunAttempt() { - return runAttempt; - } - - public int getMaxAttempts() { - return maxAttempts; - } - - public long getMaxBackoff() { - return maxBackoff; - } - - public int getMaxInstances() { - return maxInstances; - } - - public long getLifespan() { - return lifespan; - } - - public @NonNull String getSerializedData() { - return serializedData; - } - - public boolean isRunning() { - return isRunning; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - JobSpec jobSpec = (JobSpec) o; - return createTime == jobSpec.createTime && - nextRunAttemptTime == jobSpec.nextRunAttemptTime && - runAttempt == jobSpec.runAttempt && - maxAttempts == jobSpec.maxAttempts && - maxBackoff == jobSpec.maxBackoff && - lifespan == jobSpec.lifespan && - maxInstances == jobSpec.maxInstances && - isRunning == jobSpec.isRunning && - Objects.equals(id, jobSpec.id) && - Objects.equals(factoryKey, jobSpec.factoryKey) && - Objects.equals(queueKey, jobSpec.queueKey) && - Objects.equals(serializedData, jobSpec.serializedData); - } - - @Override - public int hashCode() { - return Objects.hash(id, factoryKey, queueKey, createTime, nextRunAttemptTime, runAttempt, maxAttempts, maxBackoff, lifespan, maxInstances, serializedData, isRunning); - } - - @SuppressLint("DefaultLocale") - @Override - public @NonNull String toString() { - return String.format("id: %s | factoryKey: %s | queueKey: %s | createTime: %d | nextRunAttemptTime: %d | runAttempt: %d | maxAttempts: %d | maxBackoff: %d | maxInstances: %d | lifespan: %d | isRunning: %b | data: %s", - id, factoryKey, queueKey, createTime, nextRunAttemptTime, runAttempt, maxAttempts, maxBackoff, maxInstances, lifespan, isRunning, serializedData); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/JobStorage.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/JobStorage.java deleted file mode 100644 index b7c035ac60..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/persistence/JobStorage.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.persistence; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.WorkerThread; - -import java.util.List; - -public interface JobStorage { - - @WorkerThread - void init(); - - @WorkerThread - void insertJobs(@NonNull List fullSpecs); - - @WorkerThread - @Nullable JobSpec getJobSpec(@NonNull String id); - - @WorkerThread - @NonNull List getAllJobSpecs(); - - @WorkerThread - @NonNull List getPendingJobsWithNoDependenciesInCreatedOrder(long currentTime); - - @WorkerThread - int getJobInstanceCount(@NonNull String factoryKey); - - @WorkerThread - void updateJobRunningState(@NonNull String id, boolean isRunning); - - @WorkerThread - void updateJobAfterRetry(@NonNull String id, boolean isRunning, int runAttempt, long nextRunAttemptTime); - - @WorkerThread - void updateAllJobsToBePending(); - - @WorkerThread - void deleteJob(@NonNull String id); - - @WorkerThread - void deleteJobs(@NonNull List ids); - - @WorkerThread - @NonNull List getConstraintSpecs(@NonNull String jobId); - - @WorkerThread - @NonNull List getAllConstraintSpecs(); - - @WorkerThread - @NonNull List getDependencySpecsThatDependOnJob(@NonNull String jobSpecId); - - @WorkerThread - @NonNull List getAllDependencySpecs(); -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java deleted file mode 100644 index 0bf7ea24e4..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java +++ /dev/null @@ -1,133 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - -import android.graphics.Bitmap; - -import androidx.annotation.NonNull; - -import org.session.libsession.messaging.utilities.Data; -import org.session.libsession.utilities.DownloadUtilities; -import org.session.libsession.utilities.GroupRecord; -import org.session.libsignal.exceptions.InvalidMessageException; -import org.session.libsignal.exceptions.NonSuccessfulResponseCodeException; -import org.session.libsignal.messages.SignalServiceAttachmentPointer; -import org.session.libsignal.streams.AttachmentCipherInputStream; -import org.session.libsignal.utilities.Hex; -import org.session.libsignal.utilities.Log; -import org.session.libsignal.utilities.guava.Optional; -import org.thoughtcrime.securesms.database.GroupDatabase; -import org.thoughtcrime.securesms.dependencies.DatabaseComponent; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel; -import org.thoughtcrime.securesms.util.BitmapDecodingException; -import org.thoughtcrime.securesms.util.BitmapUtil; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; - -public class AvatarDownloadJob extends BaseJob { - - public static final String KEY = "AvatarDownloadJob"; - - private static final String TAG = AvatarDownloadJob.class.getSimpleName(); - - private static final int MAX_AVATAR_SIZE = 20 * 1024 * 1024; - - private static final String KEY_GROUP_ID = "group_id"; - - private String groupId; - - public AvatarDownloadJob(@NonNull String groupId) { - this(new Job.Parameters.Builder() - .addConstraint(NetworkConstraint.KEY) - .setMaxAttempts(10) - .build(), - groupId); - } - - private AvatarDownloadJob(@NonNull Job.Parameters parameters, @NonNull String groupId) { - super(parameters); - this.groupId = groupId; - } - - @Override - public @NonNull Data serialize() { - return new Data.Builder().putString(KEY_GROUP_ID, groupId).build(); - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - public void onRun() throws IOException { - GroupDatabase database = DatabaseComponent.get(context).groupDatabase(); - Optional record = database.getGroup(groupId); - File attachment = null; - - try { - if (record.isPresent()) { - long avatarId = record.get().getAvatarId(); - String contentType = record.get().getAvatarContentType(); - byte[] key = record.get().getAvatarKey(); - String relay = record.get().getRelay(); - Optional digest = Optional.fromNullable(record.get().getAvatarDigest()); - Optional fileName = Optional.absent(); - String url = record.get().getUrl(); - - if (avatarId == -1 || key == null || url.isEmpty()) { - return; - } - - if (digest.isPresent()) { - Log.i(TAG, "Downloading group avatar with digest: " + Hex.toString(digest.get())); - } - - attachment = File.createTempFile("avatar", "tmp", context.getCacheDir()); - attachment.deleteOnExit(); - - SignalServiceAttachmentPointer pointer = new SignalServiceAttachmentPointer(avatarId, contentType, key, Optional.of(0), Optional.absent(), 0, 0, digest, fileName, false, Optional.absent(), url); - - if (pointer.getUrl().isEmpty()) throw new InvalidMessageException("Missing attachment URL."); - DownloadUtilities.downloadFile(attachment, pointer.getUrl()); - - // Assume we're retrieving an attachment for an open group server if the digest is not set - InputStream inputStream; - if (!pointer.getDigest().isPresent()) { - inputStream = new FileInputStream(attachment); - } else { - inputStream = AttachmentCipherInputStream.createForAttachment(attachment, pointer.getSize().or(0), pointer.getKey(), pointer.getDigest().get()); - } - - Bitmap avatar = BitmapUtil.createScaledBitmap(context, new AttachmentModel(attachment, key, 0, digest), 500, 500); - - database.updateProfilePicture(groupId, avatar); - inputStream.close(); - } - } catch (BitmapDecodingException | NonSuccessfulResponseCodeException | InvalidMessageException e) { - Log.w(TAG, e); - } finally { - if (attachment != null) - attachment.delete(); - } - } - - @Override - public void onCanceled() {} - - @Override - public boolean onShouldRetry(@NonNull Exception exception) { - if (exception instanceof IOException) return true; - return false; - } - - public static final class Factory implements Job.Factory { - @Override - public @NonNull AvatarDownloadJob create(@NonNull Parameters parameters, @NonNull Data data) { - return new AvatarDownloadJob(parameters, data.getString(KEY_GROUP_ID)); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/BaseJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/BaseJob.java deleted file mode 100644 index 0c11cc552b..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/BaseJob.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.jobmanager.Job; -import org.thoughtcrime.securesms.jobmanager.JobLogger; -import org.session.libsignal.utilities.Log; - -/** - * @deprecated - * use WorkManager - * API instead. - */ -public abstract class BaseJob extends Job { - - private static final String TAG = BaseJob.class.getSimpleName(); - - public BaseJob(@NonNull Parameters parameters) { - super(parameters); - } - - @Override - public @NonNull Result run() { - try { - onRun(); - return Result.SUCCESS; - } catch (Exception e) { - if (onShouldRetry(e)) { - Log.i(TAG, JobLogger.format(this, "Encountered a retryable exception."), e); - return Result.RETRY; - } else { - Log.w(TAG, JobLogger.format(this, "Encountered a failing exception."), e); - return Result.FAILURE; - } - } - } - - protected abstract void onRun() throws Exception; - - protected abstract boolean onShouldRetry(@NonNull Exception e); -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/FastJobStorage.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/FastJobStorage.java deleted file mode 100644 index 3b50dc2733..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/FastJobStorage.java +++ /dev/null @@ -1,261 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.annimon.stream.Stream; - -import org.thoughtcrime.securesms.database.JobDatabase; -import org.thoughtcrime.securesms.jobmanager.persistence.ConstraintSpec; -import org.thoughtcrime.securesms.jobmanager.persistence.DependencySpec; -import org.thoughtcrime.securesms.jobmanager.persistence.FullSpec; -import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec; -import org.thoughtcrime.securesms.jobmanager.persistence.JobStorage; - -import org.session.libsession.utilities.Util; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Set; - -public class FastJobStorage implements JobStorage { - - private final JobDatabase jobDatabase; - - private final List jobs; - private final Map> constraintsByJobId; - private final Map> dependenciesByJobId; - - public FastJobStorage(@NonNull JobDatabase jobDatabase) { - this.jobDatabase = jobDatabase; - this.jobs = new ArrayList<>(); - this.constraintsByJobId = new HashMap<>(); - this.dependenciesByJobId = new HashMap<>(); - } - - @Override - public synchronized void init() { - List jobSpecs = jobDatabase.getAllJobSpecs(); - List constraintSpecs = jobDatabase.getAllConstraintSpecs(); - List dependencySpecs = jobDatabase.getAllDependencySpecs(); - - jobs.addAll(jobSpecs); - - for (ConstraintSpec constraintSpec: constraintSpecs) { - List jobConstraints = Util.getOrDefault(constraintsByJobId, constraintSpec.getJobSpecId(), new LinkedList<>()); - jobConstraints.add(constraintSpec); - constraintsByJobId.put(constraintSpec.getJobSpecId(), jobConstraints); - } - - for (DependencySpec dependencySpec : dependencySpecs) { - List jobDependencies = Util.getOrDefault(dependenciesByJobId, dependencySpec.getJobId(), new LinkedList<>()); - jobDependencies.add(dependencySpec); - dependenciesByJobId.put(dependencySpec.getJobId(), jobDependencies); - } - } - - @Override - public synchronized void insertJobs(@NonNull List fullSpecs) { - jobDatabase.insertJobs(fullSpecs); - - for (FullSpec fullSpec : fullSpecs) { - jobs.add(fullSpec.getJobSpec()); - constraintsByJobId.put(fullSpec.getJobSpec().getId(), fullSpec.getConstraintSpecs()); - dependenciesByJobId.put(fullSpec.getJobSpec().getId(), fullSpec.getDependencySpecs()); - } - } - - @Override - public synchronized @Nullable JobSpec getJobSpec(@NonNull String id) { - for (JobSpec jobSpec : jobs) { - if (jobSpec.getId().equals(id)) { - return jobSpec; - } - } - return null; - } - - @Override - public synchronized @NonNull List getAllJobSpecs() { - return new ArrayList<>(jobs); - } - - @Override - public synchronized @NonNull List getPendingJobsWithNoDependenciesInCreatedOrder(long currentTime) { - return Stream.of(jobs) - .filter(j -> JobManagerFactories.hasFactoryForKey(j.getFactoryKey())) - .filterNot(JobSpec::isRunning) - .filter(this::firstInQueue) - .filter(j -> !dependenciesByJobId.containsKey(j.getId()) || dependenciesByJobId.get(j.getId()).isEmpty()) - .filter(j -> j.getNextRunAttemptTime() <= currentTime) - .sorted((j1, j2) -> Long.compare(j1.getCreateTime(), j2.getCreateTime())) - .toList(); - } - - private boolean firstInQueue(@NonNull JobSpec job) { - if (job.getQueueKey() == null) { - return true; - } - - return Stream.of(jobs) - .filter(j -> Util.equals(j.getQueueKey(), job.getQueueKey())) - .sorted((j1, j2) -> Long.compare(j1.getCreateTime(), j2.getCreateTime())) - .toList() - .get(0) - .equals(job); - } - - @Override - public synchronized int getJobInstanceCount(@NonNull String factoryKey) { - return (int) Stream.of(jobs) - .filter(j -> j.getFactoryKey().equals(factoryKey)) - .count(); - } - - @Override - public synchronized void updateJobRunningState(@NonNull String id, boolean isRunning) { - jobDatabase.updateJobRunningState(id, isRunning); - - ListIterator iter = jobs.listIterator(); - - while (iter.hasNext()) { - JobSpec existing = iter.next(); - if (existing.getId().equals(id)) { - JobSpec updated = new JobSpec(existing.getId(), - existing.getFactoryKey(), - existing.getQueueKey(), - existing.getCreateTime(), - existing.getNextRunAttemptTime(), - existing.getRunAttempt(), - existing.getMaxAttempts(), - existing.getMaxBackoff(), - existing.getLifespan(), - existing.getMaxInstances(), - existing.getSerializedData(), - isRunning); - iter.set(updated); - } - } - } - - @Override - public synchronized void updateJobAfterRetry(@NonNull String id, boolean isRunning, int runAttempt, long nextRunAttemptTime) { - jobDatabase.updateJobAfterRetry(id, isRunning, runAttempt, nextRunAttemptTime); - - ListIterator iter = jobs.listIterator(); - - while (iter.hasNext()) { - JobSpec existing = iter.next(); - if (existing.getId().equals(id)) { - JobSpec updated = new JobSpec(existing.getId(), - existing.getFactoryKey(), - existing.getQueueKey(), - existing.getCreateTime(), - nextRunAttemptTime, - runAttempt, - existing.getMaxAttempts(), - existing.getMaxBackoff(), - existing.getLifespan(), - existing.getMaxInstances(), - existing.getSerializedData(), - isRunning); - iter.set(updated); - } - } - } - - @Override - public synchronized void updateAllJobsToBePending() { - jobDatabase.updateAllJobsToBePending(); - - ListIterator iter = jobs.listIterator(); - - while (iter.hasNext()) { - JobSpec existing = iter.next(); - JobSpec updated = new JobSpec(existing.getId(), - existing.getFactoryKey(), - existing.getQueueKey(), - existing.getCreateTime(), - existing.getNextRunAttemptTime(), - existing.getRunAttempt(), - existing.getMaxAttempts(), - existing.getMaxBackoff(), - existing.getLifespan(), - existing.getMaxInstances(), - existing.getSerializedData(), - false); - iter.set(updated); - } - } - - @Override - public synchronized void deleteJob(@NonNull String jobId) { - deleteJobs(Collections.singletonList(jobId)); - } - - @Override - public synchronized void deleteJobs(@NonNull List jobIds) { - jobDatabase.deleteJobs(jobIds); - - Set deleteIds = new HashSet<>(jobIds); - - Iterator jobIter = jobs.iterator(); - while (jobIter.hasNext()) { - if (deleteIds.contains(jobIter.next().getId())) { - jobIter.remove(); - } - } - - for (String jobId : jobIds) { - constraintsByJobId.remove(jobId); - dependenciesByJobId.remove(jobId); - - for (Map.Entry> entry : dependenciesByJobId.entrySet()) { - Iterator depedencyIter = entry.getValue().iterator(); - - while (depedencyIter.hasNext()) { - if (depedencyIter.next().getDependsOnJobId().equals(jobId)) { - depedencyIter.remove(); - } - } - } - } - } - - @Override - public synchronized @NonNull List getConstraintSpecs(@NonNull String jobId) { - return Util.getOrDefault(constraintsByJobId, jobId, new LinkedList<>()); - } - - @Override - public synchronized @NonNull List getAllConstraintSpecs() { - return Stream.of(constraintsByJobId) - .map(Map.Entry::getValue) - .flatMap(Stream::of) - .toList(); - } - - @Override - public synchronized @NonNull List getDependencySpecsThatDependOnJob(@NonNull String jobSpecId) { - return Stream.of(dependenciesByJobId.entrySet()) - .map(Map.Entry::getValue) - .flatMap(Stream::of) - .filter(j -> j.getDependsOnJobId().equals(jobSpecId)) - .toList(); - } - - @Override - public @NonNull List getAllDependencySpecs() { - return Stream.of(dependenciesByJobId) - .map(Map.Entry::getValue) - .flatMap(Stream::of) - .toList(); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java deleted file mode 100644 index e660a774b1..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - -import android.app.Application; - -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.jobmanager.Constraint; -import org.thoughtcrime.securesms.jobmanager.ConstraintObserver; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.thoughtcrime.securesms.jobmanager.impl.CellServiceConstraint; -import org.thoughtcrime.securesms.jobmanager.impl.CellServiceConstraintObserver; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraintObserver; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint; -import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint; -import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public final class JobManagerFactories { - - private static Collection factoryKeys = new ArrayList<>(); - - public static Map getJobFactories(@NonNull Application application) { - HashMap factoryHashMap = new HashMap() {{ - put(AvatarDownloadJob.KEY, new AvatarDownloadJob.Factory()); - put(LocalBackupJob.KEY, new LocalBackupJob.Factory()); - put(RetrieveProfileAvatarJob.KEY, new RetrieveProfileAvatarJob.Factory(application)); - put(PrepareAttachmentAudioExtrasJob.KEY, new PrepareAttachmentAudioExtrasJob.Factory()); - }}; - factoryKeys.addAll(factoryHashMap.keySet()); - return factoryHashMap; - } - - public static Map getConstraintFactories(@NonNull Application application) { - return new HashMap() {{ - put(CellServiceConstraint.KEY, new CellServiceConstraint.Factory(application)); - put(NetworkConstraint.KEY, new NetworkConstraint.Factory(application)); - put(NetworkOrCellServiceConstraint.KEY, new NetworkOrCellServiceConstraint.Factory(application)); - put(SqlCipherMigrationConstraint.KEY, new SqlCipherMigrationConstraint.Factory(application)); - }}; - } - - public static List getConstraintObservers(@NonNull Application application) { - return Arrays.asList(new CellServiceConstraintObserver(application), - new NetworkConstraintObserver(application), - new SqlCipherMigrationConstraintObserver()); - } - - public static boolean hasFactoryForKey(String factoryKey) { - return factoryKeys.contains(factoryKey); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.java deleted file mode 100644 index e5715db263..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/LocalBackupJob.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - -import androidx.annotation.NonNull; - -import org.session.libsession.messaging.utilities.Data; -import org.session.libsignal.utilities.NoExternalStorageException; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.session.libsignal.utilities.Log; -import org.thoughtcrime.securesms.database.BackupFileRecord; -import org.thoughtcrime.securesms.notifications.NotificationChannels; -import org.thoughtcrime.securesms.service.GenericForegroundService; -import org.thoughtcrime.securesms.util.BackupUtil; - -import java.io.IOException; -import java.util.Collections; - -import network.loki.messenger.R; - -public class LocalBackupJob extends BaseJob { - - public static final String KEY = "LocalBackupJob"; - - private static final String TAG = LocalBackupJob.class.getSimpleName(); - - public LocalBackupJob() { - this(new Job.Parameters.Builder() - .setQueue("__LOCAL_BACKUP__") - .setMaxInstances(1) - .setMaxAttempts(3) - .build()); - } - - private LocalBackupJob(@NonNull Job.Parameters parameters) { - super(parameters); - } - - @Override - public @NonNull - Data serialize() { - return Data.EMPTY; - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - public void onRun() throws NoExternalStorageException, IOException { - Log.i(TAG, "Executing backup job..."); - - GenericForegroundService.startForegroundTask(context, - context.getString(R.string.LocalBackupJob_creating_backup), - NotificationChannels.BACKUPS, - R.drawable.ic_launcher_foreground); - - // TODO: Maybe create a new backup icon like ic_signal_backup? - - try { - BackupFileRecord record = BackupUtil.createBackupFile(context); - BackupUtil.deleteAllBackupFiles(context, Collections.singletonList(record)); - - } finally { - GenericForegroundService.stopForegroundTask(context); - } - } - - @Override - public boolean onShouldRetry(@NonNull Exception e) { - return false; - } - - @Override - public void onCanceled() { - } - - public static class Factory implements Job.Factory { - @Override - public @NonNull LocalBackupJob create(@NonNull Parameters parameters, @NonNull Data data) { - return new LocalBackupJob(parameters); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PrepareAttachmentAudioExtrasJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/PrepareAttachmentAudioExtrasJob.kt deleted file mode 100644 index 69794d41bd..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PrepareAttachmentAudioExtrasJob.kt +++ /dev/null @@ -1,133 +0,0 @@ -package org.thoughtcrime.securesms.jobs - -import android.os.Build -import org.greenrobot.eventbus.EventBus -import org.session.libsession.messaging.sending_receiving.attachments.Attachment -import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId -import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachmentAudioExtras -import org.session.libsession.messaging.utilities.Data -import org.session.libsession.utilities.DecodedAudio -import org.session.libsession.utilities.InputStreamMediaDataSource -import org.session.libsignal.utilities.Log -import org.thoughtcrime.securesms.dependencies.DatabaseComponent -import org.thoughtcrime.securesms.jobmanager.Job -import org.thoughtcrime.securesms.jobs.PrepareAttachmentAudioExtrasJob.AudioExtrasUpdatedEvent -import org.thoughtcrime.securesms.mms.PartAuthority -import java.util.* -import java.util.concurrent.TimeUnit - -/** - * Decodes the audio content of the related attachment entry - * and caches the result with [DatabaseAttachmentAudioExtras] data. - * - * It only process attachments with "audio" mime types. - * - * Due to [DecodedAudio] implementation limitations, it only works for API 23+. - * For any lower targets fake data will be generated. - * - * You can subscribe to [AudioExtrasUpdatedEvent] to be notified about the successful result. - */ -//TODO AC: Rewrite to WorkManager API when -// https://github.com/loki-project/session-android/pull/354 is merged. -class PrepareAttachmentAudioExtrasJob : BaseJob { - - companion object { - private const val TAG = "AttachAudioExtrasJob" - - const val KEY = "PrepareAttachmentAudioExtrasJob" - const val DATA_ATTACH_ID = "attachment_id" - - const val VISUAL_RMS_FRAMES = 32 // The amount of values to be computed for the visualization. - } - - private val attachmentId: AttachmentId - - constructor(attachmentId: AttachmentId) : this(Parameters.Builder() - .setQueue(KEY) - .setLifespan(TimeUnit.DAYS.toMillis(1)) - .build(), - attachmentId) - - private constructor(parameters: Parameters, attachmentId: AttachmentId) : super(parameters) { - this.attachmentId = attachmentId - } - - override fun serialize(): Data { - return Data.Builder().putParcelable(DATA_ATTACH_ID, attachmentId).build(); - } - - override fun getFactoryKey(): String { return KEY - } - - override fun onShouldRetry(e: Exception): Boolean { - return false - } - - override fun onCanceled() { } - - override fun onRun() { - Log.v(TAG, "Processing attachment: $attachmentId") - - val attachDb = DatabaseComponent.get(context).attachmentDatabase() - val attachment = attachDb.getAttachment(attachmentId) - - if (attachment == null) { - throw IllegalStateException("Cannot find attachment with the ID $attachmentId") - } - if (!attachment.contentType.startsWith("audio/")) { - throw IllegalStateException("Attachment $attachmentId is not of audio type.") - } - - // Check if the audio extras already exist. - if (attachDb.getAttachmentAudioExtras(attachmentId) != null) return - - fun extractAttachmentRandomSeed(attachment: Attachment): Int { - return when { - attachment.digest != null -> attachment.digest!!.sum() - attachment.fileName != null -> attachment.fileName.hashCode() - else -> attachment.hashCode() - } - } - - fun generateFakeRms(seed: Int, frames: Int = VISUAL_RMS_FRAMES): ByteArray { - return ByteArray(frames).apply { Random(seed.toLong()).nextBytes(this) } - } - - var rmsValues: ByteArray - var totalDurationMs: Long = DatabaseAttachmentAudioExtras.DURATION_UNDEFINED - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - // Due to API version incompatibility, we just display some random waveform for older API. - rmsValues = generateFakeRms(extractAttachmentRandomSeed(attachment)) - } else { - try { - @Suppress("BlockingMethodInNonBlockingContext") - val decodedAudio = PartAuthority.getAttachmentStream(context, attachment.dataUri!!).use { - DecodedAudio.create(InputStreamMediaDataSource(it)) - } - rmsValues = decodedAudio.calculateRms(VISUAL_RMS_FRAMES) - totalDurationMs = (decodedAudio.totalDuration / 1000.0).toLong() - } catch (e: Exception) { - Log.w(TAG, "Failed to decode sample values for the audio attachment \"${attachment.fileName}\".", e) - rmsValues = generateFakeRms(extractAttachmentRandomSeed(attachment)) - } - } - - attachDb.setAttachmentAudioExtras(DatabaseAttachmentAudioExtras( - attachmentId, - rmsValues, - totalDurationMs - )) - - EventBus.getDefault().post(AudioExtrasUpdatedEvent(attachmentId)) - } - - class Factory : Job.Factory { - override fun create(parameters: Parameters, data: Data): PrepareAttachmentAudioExtrasJob { - return PrepareAttachmentAudioExtrasJob(parameters, data.getParcelable(DATA_ATTACH_ID, AttachmentId.CREATOR)) - } - } - - /** Gets dispatched once the audio extras have been updated. */ - data class AudioExtrasUpdatedEvent(val attachmentId: AttachmentId) -} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java deleted file mode 100644 index 39b7753035..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java +++ /dev/null @@ -1,144 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - -import android.app.Application; -import android.text.TextUtils; - -import androidx.annotation.NonNull; - -import org.session.libsession.avatars.AvatarHelper; -import org.session.libsession.messaging.utilities.Data; -import org.session.libsession.utilities.Address; -import org.session.libsession.utilities.DownloadUtilities; -import org.session.libsession.utilities.TextSecurePreferences; -import org.session.libsession.utilities.Util; -import org.session.libsession.utilities.recipients.Recipient; -import org.session.libsignal.exceptions.PushNetworkException; -import org.session.libsignal.streams.ProfileCipherInputStream; -import org.session.libsignal.utilities.Log; -import org.thoughtcrime.securesms.database.RecipientDatabase; -import org.thoughtcrime.securesms.dependencies.DatabaseComponent; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.SecureRandom; -import java.util.concurrent.TimeUnit; - -public class RetrieveProfileAvatarJob extends BaseJob { - - public static final String KEY = "RetrieveProfileAvatarJob"; - - private static final String TAG = RetrieveProfileAvatarJob.class.getSimpleName(); - - private static final int MAX_PROFILE_SIZE_BYTES = 10 * 1024 * 1024; - - private static final String KEY_PROFILE_AVATAR = "profile_avatar"; - private static final String KEY_ADDRESS = "address"; - - - private String profileAvatar; - private Recipient recipient; - - public RetrieveProfileAvatarJob(Recipient recipient, String profileAvatar) { - this(new Job.Parameters.Builder() - .setQueue("RetrieveProfileAvatarJob" + recipient.getAddress().serialize()) - .addConstraint(NetworkConstraint.KEY) - .setLifespan(TimeUnit.HOURS.toMillis(1)) - .setMaxAttempts(2) - .setMaxInstances(1) - .build(), - recipient, - profileAvatar); - } - - private RetrieveProfileAvatarJob(@NonNull Job.Parameters parameters, @NonNull Recipient recipient, String profileAvatar) { - super(parameters); - this.recipient = recipient; - this.profileAvatar = profileAvatar; - } - - @Override - public @NonNull - Data serialize() { - return new Data.Builder() - .putString(KEY_PROFILE_AVATAR, profileAvatar) - .putString(KEY_ADDRESS, recipient.getAddress().serialize()) - .build(); - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - public void onRun() throws IOException { - RecipientDatabase database = DatabaseComponent.get(context).recipientDatabase(); - byte[] profileKey = recipient.resolve().getProfileKey(); - - if (profileKey == null || (profileKey.length != 32 && profileKey.length != 16)) { - Log.w(TAG, "Recipient profile key is gone!"); - return; - } - - if (AvatarHelper.avatarFileExists(context, recipient.resolve().getAddress()) && Util.equals(profileAvatar, recipient.resolve().getProfileAvatar())) { - Log.w(TAG, "Already retrieved profile avatar: " + profileAvatar); - return; - } - - if (TextUtils.isEmpty(profileAvatar)) { - Log.w(TAG, "Removing profile avatar for: " + recipient.getAddress().serialize()); - AvatarHelper.delete(context, recipient.getAddress()); - database.setProfileAvatar(recipient, profileAvatar); - return; - } - - File downloadDestination = File.createTempFile("avatar", ".jpg", context.getCacheDir()); - - try { - DownloadUtilities.downloadFile(downloadDestination, profileAvatar); - InputStream avatarStream = new ProfileCipherInputStream(new FileInputStream(downloadDestination), profileKey); - File decryptDestination = File.createTempFile("avatar", ".jpg", context.getCacheDir()); - - Util.copy(avatarStream, new FileOutputStream(decryptDestination)); - decryptDestination.renameTo(AvatarHelper.getAvatarFile(context, recipient.getAddress())); - } finally { - if (downloadDestination != null) downloadDestination.delete(); - } - - if (recipient.isLocalNumber()) { - TextSecurePreferences.setProfileAvatarId(context, new SecureRandom().nextInt()); - } - database.setProfileAvatar(recipient, profileAvatar); - } - - @Override - public boolean onShouldRetry(@NonNull Exception e) { - if (e instanceof PushNetworkException) return true; - return false; - } - - @Override - public void onCanceled() { - } - - public static final class Factory implements Job.Factory { - - private final Application application; - - public Factory(Application application) { - this.application = application; - } - - @Override - public @NonNull RetrieveProfileAvatarJob create(@NonNull Parameters parameters, @NonNull Data data) { - return new RetrieveProfileAvatarJob(parameters, - Recipient.from(application, Address.fromSerialized(data.getString(KEY_ADDRESS)), true), - data.getString(KEY_PROFILE_AVATAR)); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/logging/LogFile.java b/app/src/main/java/org/thoughtcrime/securesms/logging/LogFile.java index f0c083ca1d..909f19e08c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/logging/LogFile.java +++ b/app/src/main/java/org/thoughtcrime/securesms/logging/LogFile.java @@ -1,5 +1,7 @@ package org.thoughtcrime.securesms.logging; +import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK; + import androidx.annotation.NonNull; import org.session.libsession.utilities.Conversions; @@ -66,15 +68,17 @@ class LogFile { byte[] plaintext = entry.getBytes(); try { - cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secret, "AES"), new IvParameterSpec(ivBuffer)); + synchronized (CIPHER_LOCK) { + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secret, "AES"), new IvParameterSpec(ivBuffer)); - int cipherLength = cipher.getOutputSize(plaintext.length); - byte[] ciphertext = ciphertextBuffer.get(cipherLength); - cipherLength = cipher.doFinal(plaintext, 0, plaintext.length, ciphertext); + int cipherLength = cipher.getOutputSize(plaintext.length); + byte[] ciphertext = ciphertextBuffer.get(cipherLength); + cipherLength = cipher.doFinal(plaintext, 0, plaintext.length, ciphertext); - outputStream.write(ivBuffer); - outputStream.write(Conversions.intToByteArray(cipherLength)); - outputStream.write(ciphertext, 0, cipherLength); + outputStream.write(ivBuffer); + outputStream.write(Conversions.intToByteArray(cipherLength)); + outputStream.write(ciphertext, 0, cipherLength); + } outputStream.flush(); } catch (ShortBufferException | InvalidAlgorithmParameterException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) { @@ -134,10 +138,11 @@ class LogFile { Util.readFully(inputStream, ciphertext, length); try { - cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secret, "AES"), new IvParameterSpec(ivBuffer)); - byte[] plaintext = cipher.doFinal(ciphertext, 0, length); - - return new String(plaintext); + synchronized (CIPHER_LOCK) { + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secret, "AES"), new IvParameterSpec(ivBuffer)); + byte[] plaintext = cipher.doFinal(ciphertext, 0, length); + return new String(plaintext); + } } catch (InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) { throw new AssertionError(e); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt index 504194d3a4..a66dd7428c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt @@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.preferences import android.app.AlertDialog import android.os.Bundle -import android.view.View import androidx.activity.viewModels import androidx.core.view.isVisible import dagger.hilt.android.AndroidEntryPoint @@ -11,58 +10,26 @@ import network.loki.messenger.databinding.ActivityBlockedContactsBinding import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity @AndroidEntryPoint -class BlockedContactsActivity: PassphraseRequiredActionBarActivity(), View.OnClickListener { +class BlockedContactsActivity: PassphraseRequiredActionBarActivity() { lateinit var binding: ActivityBlockedContactsBinding val viewModel: BlockedContactsViewModel by viewModels() - val adapter = BlockedContactsAdapter() + val adapter: BlockedContactsAdapter by lazy { BlockedContactsAdapter(viewModel) } - override fun onClick(v: View?) { - if (v === binding.unblockButton && adapter.getSelectedItems().isNotEmpty()) { - val contactsToUnblock = adapter.getSelectedItems() - // show dialog - val title = if (contactsToUnblock.size == 1) { - getString(R.string.Unblock_dialog__title_single, contactsToUnblock.first().name) - } else { - getString(R.string.Unblock_dialog__title_multiple) - } + fun unblock() { + // show dialog + val title = viewModel.getTitle(this) - val message = if (contactsToUnblock.size == 1) { - getString(R.string.Unblock_dialog__message, contactsToUnblock.first().name) - } else { - val stringBuilder = StringBuilder() - val iterator = contactsToUnblock.iterator() - var numberAdded = 0 - while (iterator.hasNext() && numberAdded < 3) { - val nextRecipient = iterator.next() - if (numberAdded > 0) stringBuilder.append(", ") - - stringBuilder.append(nextRecipient.name) - numberAdded++ - } - val overflow = contactsToUnblock.size - numberAdded - if (overflow > 0) { - stringBuilder.append(" ") - val string = resources.getQuantityString(R.plurals.Unblock_dialog__message_multiple_overflow, overflow) - stringBuilder.append(string.format(overflow)) - } - getString(R.string.Unblock_dialog__message, stringBuilder.toString()) - } + val message = viewModel.getMessage(this) - AlertDialog.Builder(this) - .setTitle(title) - .setMessage(message) - .setPositiveButton(R.string.continue_2) { d, _ -> - viewModel.unblock(contactsToUnblock) - d.dismiss() - } - .setNegativeButton(R.string.cancel) { d, _ -> - d.dismiss() - } - .show() - } + AlertDialog.Builder(this) + .setTitle(title) + .setMessage(message) + .setPositiveButton(R.string.continue_2) { _, _ -> viewModel.unblock(this@BlockedContactsActivity) } + .setNegativeButton(R.string.cancel) { _, _ -> } + .show() } override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) { @@ -73,15 +40,15 @@ class BlockedContactsActivity: PassphraseRequiredActionBarActivity(), View.OnCli binding.recyclerView.adapter = adapter viewModel.subscribe(this) - .observe(this) { newState -> - adapter.submitList(newState.blockedContacts) - val isEmpty = newState.blockedContacts.isEmpty() - binding.emptyStateMessageTextView.isVisible = isEmpty - binding.nonEmptyStateGroup.isVisible = !isEmpty + .observe(this) { state -> + adapter.submitList(state.items) + binding.emptyStateMessageTextView.isVisible = state.emptyStateMessageTextViewVisible + binding.nonEmptyStateGroup.isVisible = state.nonEmptyStateGroupVisible + binding.unblockButton.isEnabled = state.unblockButtonEnabled } - binding.unblockButton.setOnClickListener(this) + binding.unblockButton.setOnClickListener { unblock() } } - -} \ No newline at end of file +} + \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt index 50af49b557..a75d53c4f1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt @@ -10,38 +10,30 @@ import network.loki.messenger.R import network.loki.messenger.databinding.BlockedContactLayoutBinding import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.mms.GlideApp +import org.thoughtcrime.securesms.util.adapter.SelectableItem -class BlockedContactsAdapter: ListAdapter(RecipientDiffer()) { +typealias SelectableRecipient = SelectableItem - class RecipientDiffer: DiffUtil.ItemCallback() { - override fun areItemsTheSame(oldItem: Recipient, newItem: Recipient) = oldItem === newItem - override fun areContentsTheSame(oldItem: Recipient, newItem: Recipient) = oldItem == newItem +class BlockedContactsAdapter(val viewModel: BlockedContactsViewModel) : ListAdapter(RecipientDiffer()) { + + class RecipientDiffer: DiffUtil.ItemCallback() { + override fun areItemsTheSame(old: SelectableRecipient, new: SelectableRecipient) = old.item.address == new.item.address + override fun areContentsTheSame(old: SelectableRecipient, new: SelectableRecipient) = old.isSelected == new.isSelected + override fun getChangePayload(old: SelectableRecipient, new: SelectableRecipient) = new.isSelected } - private val selectedItems = mutableListOf() - - fun getSelectedItems() = selectedItems - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val itemView = LayoutInflater.from(parent.context).inflate(R.layout.blocked_contact_layout, parent, false) - return ViewHolder(itemView) - } - - private fun toggleSelection(recipient: Recipient, isSelected: Boolean, position: Int) { - if (isSelected) { - selectedItems -= recipient - } else { - selectedItems += recipient - } - notifyItemChanged(position) - } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder = + LayoutInflater.from(parent.context) + .inflate(R.layout.blocked_contact_layout, parent, false) + .let(::ViewHolder) override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val recipient = getItem(position) - val isSelected = recipient in selectedItems - holder.bind(recipient, isSelected) { - toggleSelection(recipient, isSelected, position) - } + holder.bind(getItem(position), viewModel::toggle) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int, payloads: MutableList) { + if (payloads.isEmpty()) holder.bind(getItem(position), viewModel::toggle) + else holder.select(getItem(position).isSelected) } override fun onViewRecycled(holder: ViewHolder) { @@ -54,15 +46,18 @@ class BlockedContactsAdapter: ListAdapter Unit) { - binding.recipientName.text = recipient.name + fun bind(selectable: SelectableRecipient, toggle: (SelectableRecipient) -> Unit) { + binding.recipientName.text = selectable.item.name with (binding.profilePictureView.root) { glide = this@ViewHolder.glide - update(recipient) + update(selectable.item) } - binding.root.setOnClickListener { toggleSelection() } + binding.root.setOnClickListener { toggle(selectable) } + binding.selectButton.isSelected = selectable.isSelected + } + + fun select(isSelected: Boolean) { binding.selectButton.isSelected = isSelected } } - -} \ No newline at end of file +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsPreference.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsPreference.kt index 254d34978d..e985ba6d4f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsPreference.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsPreference.kt @@ -9,20 +9,15 @@ import androidx.preference.PreferenceViewHolder class BlockedContactsPreference @JvmOverloads constructor( context: Context, - attributeSet: AttributeSet? = null) : PreferenceCategory(context, attributeSet), View.OnClickListener { - - override fun onClick(v: View?) { - if (v is BlockedContactsLayout) { - val intent = Intent(context, BlockedContactsActivity::class.java) - context.startActivity(intent) - } - } + attributeSet: AttributeSet? = null +) : PreferenceCategory(context, attributeSet) { override fun onBindViewHolder(holder: PreferenceViewHolder) { super.onBindViewHolder(holder) - val itemView = holder.itemView - itemView.setOnClickListener(this) + holder.itemView.setOnClickListener { + val intent = Intent(context, BlockedContactsActivity::class.java) + context.startActivity(intent) + } } - -} \ No newline at end of file +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt index 9c0a436ebb..acbba1ebb2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt @@ -7,8 +7,10 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import app.cash.copper.flow.observeQuery import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main +import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.collect @@ -17,9 +19,12 @@ import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch import kotlinx.coroutines.plus import kotlinx.coroutines.withContext +import network.loki.messenger.R import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.database.DatabaseContentProviders import org.thoughtcrime.securesms.database.Storage +import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities +import org.thoughtcrime.securesms.util.adapter.SelectableItem import javax.inject.Inject @HiltViewModel @@ -29,7 +34,9 @@ class BlockedContactsViewModel @Inject constructor(private val storage: Storage) private val listUpdateChannel = Channel(capacity = Channel.CONFLATED) - private val _contacts = MutableLiveData(BlockedContactsViewState(emptyList())) + private val _state = MutableLiveData(BlockedContactsViewState()) + + val state get() = _state.value!! fun subscribe(context: Context): LiveData { executor.launch(IO) { @@ -45,21 +52,78 @@ class BlockedContactsViewModel @Inject constructor(private val storage: Storage) } executor.launch(IO) { for (update in listUpdateChannel) { - val blockedContactState = BlockedContactsViewState(storage.blockedContacts().sortedBy { it.name }) + val blockedContactState = state.copy( + blockedContacts = storage.blockedContacts().sortedBy { it.name } + ) withContext(Main) { - _contacts.value = blockedContactState + _state.value = blockedContactState } } } - return _contacts + return _state } - fun unblock(toUnblock: List) { - storage.unblock(toUnblock) + fun unblock(context: Context) { + storage.unblock(state.selectedItems) + _state.value = state.copy(selectedItems = emptySet()) + // TODO: Remove in UserConfig branch + GlobalScope.launch(Dispatchers.IO) { + ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context) + } + } + + fun select(selectedItem: Recipient, isSelected: Boolean) { + _state.value = state.run { + if (isSelected) copy(selectedItems = selectedItems + selectedItem) + else copy(selectedItems = selectedItems - selectedItem) + } + } + + fun getTitle(context: Context): String = + if (state.selectedItems.size == 1) { + context.getString(R.string.Unblock_dialog__title_single, state.selectedItems.first().name) + } else { + context.getString(R.string.Unblock_dialog__title_multiple) + } + + fun getMessage(context: Context): String { + if (state.selectedItems.size == 1) { + return context.getString(R.string.Unblock_dialog__message, state.selectedItems.first().name) + } + val stringBuilder = StringBuilder() + val iterator = state.selectedItems.iterator() + var numberAdded = 0 + while (iterator.hasNext() && numberAdded < 3) { + val nextRecipient = iterator.next() + if (numberAdded > 0) stringBuilder.append(", ") + + stringBuilder.append(nextRecipient.name) + numberAdded++ + } + val overflow = state.selectedItems.size - numberAdded + if (overflow > 0) { + stringBuilder.append(" ") + val string = context.resources.getQuantityString(R.plurals.Unblock_dialog__message_multiple_overflow, overflow) + stringBuilder.append(string.format(overflow)) + } + return context.getString(R.string.Unblock_dialog__message, stringBuilder.toString()) + } + + fun toggle(selectable: SelectableItem) { + _state.value = state.run { + if (selectable.item in selectedItems) copy(selectedItems = selectedItems - selectable.item) + else copy(selectedItems = selectedItems + selectable.item) + } } data class BlockedContactsViewState( - val blockedContacts: List - ) + val blockedContacts: List = emptyList(), + val selectedItems: Set = emptySet() + ) { + val items = blockedContacts.map { SelectableItem(it, it in selectedItems) } -} \ No newline at end of file + val unblockButtonEnabled get() = selectedItems.isNotEmpty() + val emptyStateMessageTextViewVisible get() = blockedContacts.isEmpty() + val nonEmptyStateGroupVisible get() = blockedContacts.isNotEmpty() + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/ClearAllDataDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/ClearAllDataDialog.kt index 560c137104..fa3be71307 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/ClearAllDataDialog.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/ClearAllDataDialog.kt @@ -42,6 +42,7 @@ class ClearAllDataDialog : BaseDialog() { var selectedOption = device val optionAdapter = RadioOptionAdapter { selectedOption = it } binding.recyclerView.apply { + itemAnimator = null adapter = optionAdapter addItemDecoration(DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)) setHasFixedSize(true) diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/ListPreferenceDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/ListPreferenceDialog.kt index e407c67774..2ba48f6e41 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/ListPreferenceDialog.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/ListPreferenceDialog.kt @@ -1,42 +1,41 @@ package org.thoughtcrime.securesms.preferences +import android.content.Context import android.view.LayoutInflater import androidx.appcompat.app.AlertDialog import androidx.preference.ListPreference -import androidx.recyclerview.widget.DividerItemDecoration import network.loki.messenger.databinding.DialogListPreferenceBinding -import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog -class ListPreferenceDialog( - private val listPreference: ListPreference, - private val dialogListener: () -> Unit -) : BaseDialog() { - private lateinit var binding: DialogListPreferenceBinding +fun listPreferenceDialog( + context: Context, + listPreference: ListPreference, + dialogListener: () -> Unit +) : AlertDialog { - override fun setContentView(builder: AlertDialog.Builder) { - binding = DialogListPreferenceBinding.inflate(LayoutInflater.from(requireContext())) - binding.titleTextView.text = listPreference.dialogTitle - binding.messageTextView.text = listPreference.dialogMessage - binding.closeButton.setOnClickListener { - dismiss() - } - val options = listPreference.entryValues.zip(listPreference.entries) { value, title -> - RadioOption(value.toString(), title.toString()) - } - val valueIndex = listPreference.findIndexOfValue(listPreference.value) - val optionAdapter = RadioOptionAdapter(valueIndex) { - listPreference.value = it.value - dismiss() - dialogListener.invoke() - } - binding.recyclerView.apply { - adapter = optionAdapter - addItemDecoration(DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)) - setHasFixedSize(true) - } - optionAdapter.submitList(options) - builder.setView(binding.root) - builder.setCancelable(false) + val builder = AlertDialog.Builder(context) + + val binding = DialogListPreferenceBinding.inflate(LayoutInflater.from(context)) + binding.titleTextView.text = listPreference.dialogTitle + binding.messageTextView.text = listPreference.dialogMessage + + builder.setView(binding.root) + + val dialog = builder.show() + + val valueIndex = listPreference.findIndexOfValue(listPreference.value) + RadioOptionAdapter(valueIndex) { + listPreference.value = it.value + dialog.dismiss() + dialogListener() } + .apply { + listPreference.entryValues.zip(listPreference.entries) { value, title -> + RadioOption(value.toString(), title.toString()) + }.let(this::submitList) + } + .let { binding.recyclerView.adapter = it } -} \ No newline at end of file + binding.closeButton.setOnClickListener { dialog.dismiss() } + + return dialog +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java b/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java index efc20aca4c..8afc0ff41b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java @@ -2,6 +2,8 @@ package org.thoughtcrime.securesms.preferences; import static android.app.Activity.RESULT_OK; +import static org.thoughtcrime.securesms.preferences.ListPreferenceDialogKt.listPreferenceDialog; + import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; @@ -77,10 +79,10 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme .setOnPreferenceClickListener(preference -> { ListPreference listPreference = (ListPreference) preference; listPreference.setDialogMessage(R.string.preferences_notifications__content_message); - new ListPreferenceDialog(listPreference, () -> { - initializeListSummary((ListPreference) findPreference(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF)); + listPreferenceDialog(getContext(), listPreference, () -> { + initializeListSummary(findPreference(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF)); return null; - }).show(getChildFragmentManager(), "ListPreferenceDialog"); + }); return true; }); diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/RadioOptionAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/RadioOptionAdapter.kt index 2cb61a0e82..4bb69c4c14 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/RadioOptionAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/RadioOptionAdapter.kt @@ -16,8 +16,8 @@ class RadioOptionAdapter( ) : ListAdapter(RadioOptionDiffer()) { class RadioOptionDiffer: DiffUtil.ItemCallback() { - override fun areItemsTheSame(oldItem: RadioOption, newItem: RadioOption) = oldItem === newItem - override fun areContentsTheSame(oldItem: RadioOption, newItem: RadioOption) = oldItem == newItem + override fun areItemsTheSame(oldItem: RadioOption, newItem: RadioOption) = oldItem.title == newItem.title + override fun areContentsTheSame(oldItem: RadioOption, newItem: RadioOption) = oldItem.value == newItem.value } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { @@ -31,7 +31,7 @@ class RadioOptionAdapter( holder.bind(option, isSelected) { onClickListener(it) selectedOptionPosition = position - notifyDataSetChanged() + notifyItemRangeChanged(0, itemCount) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt index 0a56c5058d..5a03cebc37 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt @@ -2,10 +2,7 @@ package org.thoughtcrime.securesms.preferences import android.Manifest import android.app.Activity -import android.content.ClipData -import android.content.ClipboardManager -import android.content.Context -import android.content.Intent +import android.content.* import android.net.Uri import android.os.AsyncTask import android.os.Bundle @@ -19,6 +16,7 @@ import android.view.MenuItem import android.view.View import android.view.inputmethod.InputMethodManager import android.widget.Toast +import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible import network.loki.messenger.BuildConfig import network.loki.messenger.R @@ -28,13 +26,13 @@ import nl.komponents.kovenant.all import nl.komponents.kovenant.ui.alwaysUi import nl.komponents.kovenant.ui.successUi import org.session.libsession.avatars.AvatarHelper -import org.session.libsession.utilities.Address -import org.session.libsession.utilities.ProfileKeyUtil -import org.session.libsession.utilities.ProfilePictureUtilities +import org.session.libsession.avatars.ProfileContactPhoto +import org.session.libsession.utilities.* import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol -import org.session.libsession.utilities.TextSecurePreferences +import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity import org.thoughtcrime.securesms.avatar.AvatarSelection +import org.thoughtcrime.securesms.components.ProfilePictureView import org.thoughtcrime.securesms.home.PathActivity import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity import org.thoughtcrime.securesms.mms.GlideApp @@ -57,8 +55,6 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { private var displayNameEditActionMode: ActionMode? = null set(value) { field = value; handleDisplayNameEditActionModeChanged() } private lateinit var glide: GlideRequests - private var displayNameToBeUploaded: String? = null - private var profilePictureToBeUploaded: ByteArray? = null private var tempFile: File? = null private val hexEncodedPublicKey: String @@ -76,14 +72,10 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { super.onCreate(savedInstanceState, isReady) binding = ActivitySettingsBinding.inflate(layoutInflater) setContentView(binding.root) - val displayName = TextSecurePreferences.getProfileName(this) ?: hexEncodedPublicKey + val displayName = getDisplayName() glide = GlideApp.with(this) with(binding) { - profilePictureView.root.glide = glide - profilePictureView.root.publicKey = hexEncodedPublicKey - profilePictureView.root.displayName = displayName - profilePictureView.root.isLarge = true - profilePictureView.root.update() + setupProfilePictureView(profilePictureView.root) profilePictureView.root.setOnClickListener { showEditProfilePictureUI() } ctnGroupNameSection.setOnClickListener { startActionMode(DisplayNameEditActionModeCallback()) } btnGroupNameDisplay.text = displayName @@ -105,6 +97,19 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { } } + private fun getDisplayName(): String = + TextSecurePreferences.getProfileName(this) ?: truncateIdForDisplay(hexEncodedPublicKey) + + private fun setupProfilePictureView(view: ProfilePictureView) { + view.glide = glide + view.apply { + publicKey = hexEncodedPublicKey + displayName = getDisplayName() + isLarge = true + update() + } + } + override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) val scrollBundle = SparseArray() @@ -154,9 +159,9 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { } AsyncTask.execute { try { - profilePictureToBeUploaded = BitmapUtil.createScaledBytes(this@SettingsActivity, AvatarSelection.getResultUri(data), ProfileMediaConstraints()).bitmap + val profilePictureToBeUploaded = BitmapUtil.createScaledBytes(this@SettingsActivity, AvatarSelection.getResultUri(data), ProfileMediaConstraints()).bitmap Handler(Looper.getMainLooper()).post { - updateProfile(true) + updateProfile(true, profilePictureToBeUploaded) } } catch (e: BitmapDecodingException) { e.printStackTrace() @@ -190,23 +195,30 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { } } - private fun updateProfile(isUpdatingProfilePicture: Boolean) { + private fun updateProfile( + isUpdatingProfilePicture: Boolean, + profilePicture: ByteArray? = null, + displayName: String? = null + ) { binding.loader.isVisible = true val promises = mutableListOf>() - val displayName = displayNameToBeUploaded if (displayName != null) { TextSecurePreferences.setProfileName(this, displayName) } - val profilePicture = profilePictureToBeUploaded val encodedProfileKey = ProfileKeyUtil.generateEncodedProfileKey(this) - if (isUpdatingProfilePicture && profilePicture != null) { - promises.add(ProfilePictureUtilities.upload(profilePicture, encodedProfileKey, this)) + if (isUpdatingProfilePicture) { + if (profilePicture != null) { + promises.add(ProfilePictureUtilities.upload(profilePicture, encodedProfileKey, this)) + } else { + TextSecurePreferences.setLastProfilePictureUpload(this, System.currentTimeMillis()) + TextSecurePreferences.setProfilePictureURL(this, null) + } } val compoundPromise = all(promises) compoundPromise.successUi { // Do this on the UI thread so that it happens before the alwaysUi clause below - if (isUpdatingProfilePicture && profilePicture != null) { + if (isUpdatingProfilePicture) { AvatarHelper.setAvatar(this, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)!!), profilePicture) - TextSecurePreferences.setProfileAvatarId(this, SecureRandom().nextInt()) + TextSecurePreferences.setProfileAvatarId(this, profilePicture?.let { SecureRandom().nextInt() } ?: 0 ) TextSecurePreferences.setLastProfilePictureUpload(this, Date().time) ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey) } @@ -218,12 +230,10 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { if (displayName != null) { binding.btnGroupNameDisplay.text = displayName } - if (isUpdatingProfilePicture && profilePicture != null) { + if (isUpdatingProfilePicture) { binding.profilePictureView.root.recycle() // Clear the cached image before updating binding.profilePictureView.root.update() } - displayNameToBeUploaded = null - profilePictureToBeUploaded = null binding.loader.isVisible = false } } @@ -244,8 +254,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { Toast.makeText(this, R.string.activity_settings_display_name_too_long_error, Toast.LENGTH_SHORT).show() return false } - displayNameToBeUploaded = displayName - updateProfile(false) + updateProfile(false, displayName = displayName) return true } @@ -255,6 +264,38 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { } private fun showEditProfilePictureUI() { + AlertDialog.Builder(this) + .setTitle(R.string.activity_settings_set_display_picture) + .setView(R.layout.dialog_change_avatar) + .setPositiveButton(R.string.activity_settings_upload) { _, _ -> + startAvatarSelection() + } + .setNegativeButton(R.string.cancel) { _, _ -> } + .apply { + if (TextSecurePreferences.getProfileAvatarId(context) != 0) { + setNeutralButton(R.string.activity_settings_remove) { _, _ -> removeAvatar() } + } + } + .show().apply { + val profilePic = findViewById(R.id.profile_picture_view) + ?.also(::setupProfilePictureView) + + val pictureIcon = findViewById(R.id.ic_pictures) + + val recipient = Recipient.from(context, Address.fromSerialized(hexEncodedPublicKey), false) + + val photoSet = (recipient.contactPhoto as ProfileContactPhoto).avatarObject !in setOf("0", "") + + profilePic?.isVisible = photoSet + pictureIcon?.isVisible = !photoSet + } + } + + private fun removeAvatar() { + updateProfile(true) + } + + private fun startAvatarSelection() { // Ask for an optional camera permission. Permissions.with(this) .request(Manifest.permission.CAMERA) diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/LocalBackupListener.java b/app/src/main/java/org/thoughtcrime/securesms/service/LocalBackupListener.java deleted file mode 100644 index 0b1b3f8423..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/service/LocalBackupListener.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.thoughtcrime.securesms.service; - -import android.content.Context; -import android.content.Intent; - -import org.thoughtcrime.securesms.ApplicationContext; -import org.thoughtcrime.securesms.jobs.LocalBackupJob; -import org.session.libsession.utilities.TextSecurePreferences; - -import java.util.concurrent.TimeUnit; - -public class LocalBackupListener extends PersistentAlarmManagerListener { - - private static final long INTERVAL = TimeUnit.DAYS.toMillis(1); - - @Override - protected long getNextScheduledExecutionTime(Context context) { - return TextSecurePreferences.getNextBackupTime(context); - } - - @Override - protected long onAlarm(Context context, long scheduledTime) { - if (TextSecurePreferences.isBackupEnabled(context)) { - ApplicationContext.getInstance(context).getJobManager().add(new LocalBackupJob()); - } - - long nextTime = System.currentTimeMillis() + INTERVAL; - TextSecurePreferences.setNextBackupTime(context, nextTime); - - return nextTime; - } - - public static void schedule(Context context) { - if (TextSecurePreferences.isBackupEnabled(context)) { - new LocalBackupListener().onReceive(context, new Intent()); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt b/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt index b5e9b78a74..3ae3d30f01 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/service/WebRtcCallService.kt @@ -799,6 +799,7 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener { wantsToAnswerReceiver?.let { receiver -> LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver) } + callManager.shutDownAudioManager() powerButtonReceiver = null wiredHeadsetStateReceiver = null networkChangedReceiver = null diff --git a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt index c46f75bff8..f9f5524efa 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt @@ -2,11 +2,11 @@ package org.thoughtcrime.securesms.sskenvironment import android.content.Context import org.session.libsession.messaging.contacts.Contact +import org.session.libsession.messaging.jobs.JobQueue import org.session.libsession.utilities.SSKEnvironment import org.session.libsession.utilities.recipients.Recipient -import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.dependencies.DatabaseComponent -import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob +import org.session.libsession.messaging.jobs.RetrieveProfileAvatarJob class ProfileManager : SSKEnvironment.ProfileManagerProtocol { @@ -40,9 +40,8 @@ class ProfileManager : SSKEnvironment.ProfileManagerProtocol { } override fun setProfilePictureURL(context: Context, recipient: Recipient, profilePictureURL: String) { - val job = RetrieveProfileAvatarJob(recipient, profilePictureURL) - val jobManager = ApplicationContext.getInstance(context).jobManager - jobManager.add(job) + val job = RetrieveProfileAvatarJob(profilePictureURL, recipient.address) + JobQueue.shared.add(job) val sessionID = recipient.address.serialize() val contactDatabase = DatabaseComponent.get(context).sessionContactDatabase() var contact = contactDatabase.getContactWithSessionID(sessionID) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/BackupUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/util/BackupUtil.kt deleted file mode 100644 index 074278cb92..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/util/BackupUtil.kt +++ /dev/null @@ -1,313 +0,0 @@ -package org.thoughtcrime.securesms.util - -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.net.Uri -import android.os.Build -import android.os.Environment -import android.provider.DocumentsContract -import android.widget.Toast -import androidx.annotation.WorkerThread -import androidx.documentfile.provider.DocumentFile -import androidx.fragment.app.Fragment -import network.loki.messenger.R -import org.greenrobot.eventbus.EventBus -import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsignal.utilities.ByteUtil -import org.session.libsignal.utilities.Log -import org.thoughtcrime.securesms.backup.BackupEvent -import org.thoughtcrime.securesms.backup.BackupPassphrase -import org.thoughtcrime.securesms.backup.BackupProtos.SharedPreference -import org.thoughtcrime.securesms.backup.FullBackupExporter -import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider -import org.thoughtcrime.securesms.crypto.IdentityKeyUtil -import org.thoughtcrime.securesms.database.BackupFileRecord -import org.thoughtcrime.securesms.dependencies.DatabaseComponent -import java.io.IOException -import java.security.MessageDigest -import java.security.NoSuchAlgorithmException -import java.security.SecureRandom -import java.text.SimpleDateFormat -import java.util.* - -object BackupUtil { - private const val MASTER_SECRET_UTIL_PREFERENCES_NAME = "SecureSMS-Preferences" - private const val TAG = "BackupUtil" - const val BACKUP_FILE_MIME_TYPE = "application/session-backup" - const val BACKUP_PASSPHRASE_LENGTH = 30 - - fun getBackupRecords(context: Context): List { - val prefName = MASTER_SECRET_UTIL_PREFERENCES_NAME - val preferences = context.getSharedPreferences(prefName, 0) - val prefList = LinkedList() - prefList.add(SharedPreference.newBuilder() - .setFile(prefName) - .setKey(IdentityKeyUtil.IDENTITY_PUBLIC_KEY_PREF) - .setValue(preferences.getString(IdentityKeyUtil.IDENTITY_PUBLIC_KEY_PREF, null)) - .build()) - prefList.add(SharedPreference.newBuilder() - .setFile(prefName) - .setKey(IdentityKeyUtil.IDENTITY_PRIVATE_KEY_PREF) - .setValue(preferences.getString(IdentityKeyUtil.IDENTITY_PRIVATE_KEY_PREF, null)) - .build()) - if (preferences.contains(IdentityKeyUtil.ED25519_PUBLIC_KEY)) { - prefList.add(SharedPreference.newBuilder() - .setFile(prefName) - .setKey(IdentityKeyUtil.ED25519_PUBLIC_KEY) - .setValue(preferences.getString(IdentityKeyUtil.ED25519_PUBLIC_KEY, null)) - .build()) - } - if (preferences.contains(IdentityKeyUtil.ED25519_SECRET_KEY)) { - prefList.add(SharedPreference.newBuilder() - .setFile(prefName) - .setKey(IdentityKeyUtil.ED25519_SECRET_KEY) - .setValue(preferences.getString(IdentityKeyUtil.ED25519_SECRET_KEY, null)) - .build()) - } - prefList.add(SharedPreference.newBuilder() - .setFile(prefName) - .setKey(IdentityKeyUtil.LOKI_SEED) - .setValue(preferences.getString(IdentityKeyUtil.LOKI_SEED, null)) - .build()) - return prefList - } - - @JvmStatic - fun getLastBackupTimeString(context: Context, locale: Locale): String { - val timestamp = DatabaseComponent.get(context).lokiBackupFilesDatabase().getLastBackupFileTime() - if (timestamp == null) { - return context.getString(R.string.BackupUtil_never) - } - return DateUtils.getDisplayFormattedTimeSpanString(context, locale, timestamp.time) - } - - @JvmStatic - fun getLastBackup(context: Context): BackupFileRecord? { - return DatabaseComponent.get(context).lokiBackupFilesDatabase().getLastBackupFile() - } - - @JvmStatic - fun generateBackupPassphrase(): Array { - val random = ByteArray(BACKUP_PASSPHRASE_LENGTH).also { SecureRandom().nextBytes(it) } - return Array(6) { i -> - String.format("%05d", ByteUtil.byteArray5ToLong(random, i * 5) % 100000) - } - } - - @JvmStatic - fun validateDirAccess(context: Context, dirUri: Uri): Boolean { - val hasWritePermission = context.contentResolver.persistedUriPermissions.any { - it.isWritePermission && it.uri == dirUri - } - if (!hasWritePermission) return false - - val document = DocumentFile.fromTreeUri(context, dirUri) - if (document == null || !document.exists()) { - return false - } - - return true - } - - @JvmStatic - fun getBackupDirUri(context: Context): Uri? { - val dirUriString = TextSecurePreferences.getBackupSaveDir(context) ?: return null - return Uri.parse(dirUriString) - } - - @JvmStatic - fun setBackupDirUri(context: Context, uriString: String?) { - TextSecurePreferences.setBackupSaveDir(context, uriString) - } - - /** - * @return The selected backup directory if it's valid (exists, is writable). - */ - @JvmStatic - fun getSelectedBackupDirIfValid(context: Context): Uri? { - val dirUri = getBackupDirUri(context) - - if (dirUri == null) { - Log.v(TAG, "The backup dir wasn't selected yet.") - return null - } - if (!validateDirAccess(context, dirUri)) { - Log.v(TAG, "Cannot validate the access to the dir $dirUri.") - return null - } - - return dirUri; - } - - @JvmStatic - @WorkerThread - @Throws(IOException::class) - fun createBackupFile(context: Context): BackupFileRecord { - val backupPassword = BackupPassphrase.get(context) - ?: throw IOException("Backup password is null") - - val dirUri = getSelectedBackupDirIfValid(context) - ?: throw IOException("Backup save directory is not selected or invalid") - - val date = Date() - val timestamp = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US).format(date) - val fileName = String.format("session-%s.backup", timestamp) - - val fileUri = DocumentsContract.createDocument( - context.contentResolver, - DocumentFile.fromTreeUri(context, dirUri)!!.uri, - BACKUP_FILE_MIME_TYPE, - fileName) - - if (fileUri == null) { - Toast.makeText(context, "Cannot create writable file in the dir $dirUri", Toast.LENGTH_LONG).show() - throw IOException("Cannot create writable file in the dir $dirUri") - } - - try { - FullBackupExporter.export(context, - AttachmentSecretProvider.getInstance(context).orCreateAttachmentSecret, - DatabaseComponent.get(context).openHelper().readableDatabase, - fileUri, - backupPassword) - } catch (e: Exception) { - // Delete the backup file on any error. - DocumentsContract.deleteDocument(context.contentResolver, fileUri) - throw e - } - - //TODO Use real file size. - val record = DatabaseComponent.get(context).lokiBackupFilesDatabase() - .insertBackupFile(BackupFileRecord(fileUri, -1, date)) - - Log.v(TAG, "A backup file was created: $fileUri") - - return record - } - - @JvmStatic - @JvmOverloads - fun deleteAllBackupFiles(context: Context, except: Collection? = null) { - val db = DatabaseComponent.get(context).lokiBackupFilesDatabase() - db.getBackupFiles().iterator().forEach { record -> - if (except != null && except.contains(record)) return@forEach - - // Try to delete the related file. The operation may fail in many cases - // (the user moved/deleted the file, revoked the write permission, etc), so that's OK. - try { - val result = DocumentsContract.deleteDocument(context.contentResolver, record.uri) - if (!result) { - Log.w(TAG, "Failed to delete backup file: ${record.uri}") - } - } catch (e: Exception) { - Log.w(TAG, "Failed to delete backup file: ${record.uri}", e) - } - - db.deleteBackupFile(record) - - Log.v(TAG, "Backup file was deleted: ${record.uri}") - } - } - - @JvmStatic - fun computeBackupKey(passphrase: String, salt: ByteArray?): ByteArray { - return try { - EventBus.getDefault().post(BackupEvent.createProgress(0)) - val digest = MessageDigest.getInstance("SHA-512") - val input = passphrase.replace(" ", "").toByteArray() - var hash: ByteArray = input - if (salt != null) digest.update(salt) - for (i in 0..249999) { - if (i % 1000 == 0) EventBus.getDefault().post(BackupEvent.createProgress(0)) - digest.update(hash) - hash = digest.digest(input) - } - ByteUtil.trim(hash, 32) - } catch (e: NoSuchAlgorithmException) { - throw AssertionError(e) - } - } -} - -/** - * An utility class to help perform backup directory selection requests. - * - * An instance of this class should be created per an [Activity] or [Fragment] - * and [onActivityResult] should be called appropriately. - */ -class BackupDirSelector(private val contextProvider: ContextProvider) { - - companion object { - private const val REQUEST_CODE_SAVE_DIR = 7844 - } - - private val context: Context get() = contextProvider.getContext() - - private var listener: Listener? = null - - constructor(activity: Activity) : - this(ActivityContextProvider(activity)) - - constructor(fragment: Fragment) : - this(FragmentContextProvider(fragment)) - - /** - * Performs ACTION_OPEN_DOCUMENT_TREE intent to select backup directory URI. - * If the directory is already selected and valid, the request will be skipped. - * @param force if true, the previous selection is ignored and the user is requested to select another directory. - * @param onSelectedListener an optional action to perform once the directory is selected. - */ - fun selectBackupDir(force: Boolean, onSelectedListener: Listener? = null) { - if (!force) { - val dirUri = BackupUtil.getSelectedBackupDirIfValid(context) - if (dirUri != null && onSelectedListener != null) { - onSelectedListener.onBackupDirSelected(dirUri) - } - return - } - - // Let user pick the dir. - val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) - - // Request read/write permission grant for the dir. - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or - Intent.FLAG_GRANT_WRITE_URI_PERMISSION or - Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) - - // Set the default dir. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val dirUri = BackupUtil.getBackupDirUri(context) - intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, dirUri - ?: Uri.fromFile(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS))) - } - - if (onSelectedListener != null) { - this.listener = onSelectedListener - } - - contextProvider.startActivityForResult(intent, REQUEST_CODE_SAVE_DIR) - } - - fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - if (requestCode != REQUEST_CODE_SAVE_DIR) return - - if (resultCode == Activity.RESULT_OK && data != null && data.data != null) { - // Acquire persistent access permissions for the file selected. - val persistentFlags: Int = data.flags and - (Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION) - context.contentResolver.takePersistableUriPermission(data.data!!, persistentFlags) - - BackupUtil.setBackupDirUri(context, data.dataString) - - listener?.onBackupDirSelected(data.data!!) - } - - listener = null - } - - @FunctionalInterface - interface Listener { - fun onBackupDirSelected(uri: Uri) - } -} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/CursorUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/util/CursorUtil.kt new file mode 100644 index 0000000000..9cff8c77bc --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/util/CursorUtil.kt @@ -0,0 +1,6 @@ +package org.thoughtcrime.securesms.util + +import android.database.Cursor + +fun Cursor.asSequence(): Sequence = + generateSequence { if (moveToNext()) this else null } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/GeneralUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/util/GeneralUtilities.kt index 00e3e44418..a38c93831e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/GeneralUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/GeneralUtilities.kt @@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.util import android.content.res.Resources import android.os.Build import androidx.annotation.ColorRes +import androidx.recyclerview.widget.RecyclerView +import kotlin.math.max import kotlin.math.roundToInt fun Resources.getColorWithID(@ColorRes id: Int, theme: Resources.Theme?): Int { @@ -30,3 +32,8 @@ fun toDp(px: Float, resources: Resources): Float { val scale = resources.displayMetrics.density return (px / scale) } + +val RecyclerView.isScrolledToBottom: Boolean + get() = computeVerticalScrollOffset().coerceAtLeast(0) + + computeVerticalScrollExtent() + + toPx(50, resources) >= computeVerticalScrollRange() diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt index 7b7f3a04f3..8345473490 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt @@ -5,14 +5,18 @@ import android.animation.AnimatorListenerAdapter import android.animation.FloatEvaluator import android.animation.ValueAnimator import android.content.Context +import android.graphics.Bitmap import android.graphics.PointF import android.graphics.Rect +import android.util.Size import android.view.View import androidx.annotation.ColorInt import androidx.annotation.DimenRes import network.loki.messenger.R import org.session.libsession.utilities.getColorFromAttr import android.view.inputmethod.InputMethodManager +import androidx.core.graphics.applyCanvas +import kotlin.math.roundToInt fun View.contains(point: PointF): Boolean { return hitRect.contains(point.x.toInt(), point.y.toInt()) @@ -65,3 +69,24 @@ fun View.hideKeyboard() { val imm = this.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(this.windowToken, 0) } + + +fun View.drawToBitmap(config: Bitmap.Config = Bitmap.Config.ARGB_8888, longestWidth: Int = 2000): Bitmap { + val size = Size(measuredWidth, measuredHeight).coerceAtMost(longestWidth) + val scale = size.width / measuredWidth.toFloat() + + return Bitmap.createBitmap(size.width, size.height, config).applyCanvas { + scale(scale, scale) + translate(-scrollX.toFloat(), -scrollY.toFloat()) + draw(this) + } +} + +fun Size.coerceAtMost(longestWidth: Int): Size = + (width.toFloat() / height).let { aspect -> + if (aspect > 1) { + width.coerceAtMost(longestWidth).let { Size(it, (it / aspect).roundToInt()) } + } else { + height.coerceAtMost(longestWidth).let { Size((it * aspect).roundToInt(), it) } + } + } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/adapter/SelectableItem.kt b/app/src/main/java/org/thoughtcrime/securesms/util/adapter/SelectableItem.kt new file mode 100644 index 0000000000..88b41d11cd --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/util/adapter/SelectableItem.kt @@ -0,0 +1,3 @@ +package org.thoughtcrime.securesms.util.adapter + +data class SelectableItem(val item: T, val isSelected: Boolean) diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt index 07e73bedd2..d96de5eedb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/CallManager.kt @@ -93,6 +93,10 @@ class CallManager(context: Context, audioManager: AudioManagerCompat, private va peerConnectionObservers.remove(listener) } + fun shutDownAudioManager() { + signalAudioManager.shutdown() + } + private val _audioEvents = MutableStateFlow(AudioEnabled(false)) val audioEvents = _audioEvents.asSharedFlow() private val _videoEvents = MutableStateFlow(VideoEnabled(false)) diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioHandler.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioHandler.kt index 89eba2a3aa..7ca44f46dc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioHandler.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioHandler.kt @@ -15,7 +15,7 @@ class SignalAudioHandler(looper: Looper) : Handler(looper) { } } - fun isOnHandler(): Boolean { + private fun isOnHandler(): Boolean { return Looper.myLooper() == looper } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt index 67514c58be..229cbd13dd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/webrtc/audio/SignalAudioManager.kt @@ -9,6 +9,7 @@ import android.media.SoundPool import android.os.HandlerThread import network.loki.messenger.R import org.session.libsignal.utilities.Log +import org.session.libsignal.utilities.ThreadUtils import org.thoughtcrime.securesms.webrtc.AudioManagerCommand import org.thoughtcrime.securesms.webrtc.audio.SignalBluetoothManager.State as BState @@ -32,10 +33,10 @@ class SignalAudioManager(private val context: Context, private val eventListener: EventListener?, private val androidAudioManager: AudioManagerCompat) { - private var commandAndControlThread: HandlerThread? = HandlerThread("call-audio").apply { start() } - private var handler: SignalAudioHandler? = null + private var commandAndControlThread: HandlerThread? = HandlerThread("call-audio", ThreadUtils.PRIORITY_IMPORTANT_BACKGROUND_THREAD).apply { start() } + private var handler: SignalAudioHandler = SignalAudioHandler(commandAndControlThread!!.looper) - private var signalBluetoothManager: SignalBluetoothManager? = null + private var signalBluetoothManager: SignalBluetoothManager = SignalBluetoothManager(context, this, androidAudioManager, handler) private var state: State = State.UNINITIALIZED @@ -62,12 +63,9 @@ class SignalAudioManager(private val context: Context, private var wiredHeadsetReceiver: WiredHeadsetReceiver? = null fun handleCommand(command: AudioManagerCommand) { - if (command == AudioManagerCommand.Initialize) { - initialize() - return - } - handler?.post { + handler.post { when (command) { + is AudioManagerCommand.Initialize -> initialize() is AudioManagerCommand.UpdateAudioDeviceState -> updateAudioDeviceState() is AudioManagerCommand.Start -> start() is AudioManagerCommand.Stop -> stop(command.playDisconnect) @@ -84,34 +82,37 @@ class SignalAudioManager(private val context: Context, Log.i(TAG, "Initializing audio manager state: $state") if (state == State.UNINITIALIZED) { - commandAndControlThread = HandlerThread("call-audio").apply { start() } - handler = SignalAudioHandler(commandAndControlThread!!.looper) + savedAudioMode = androidAudioManager.mode + savedIsSpeakerPhoneOn = androidAudioManager.isSpeakerphoneOn + savedIsMicrophoneMute = androidAudioManager.isMicrophoneMute + hasWiredHeadset = androidAudioManager.isWiredHeadsetOn - signalBluetoothManager = SignalBluetoothManager(context, this, androidAudioManager, handler!!) + androidAudioManager.requestCallAudioFocus() - handler!!.post { + setMicrophoneMute(false) - savedAudioMode = androidAudioManager.mode - savedIsSpeakerPhoneOn = androidAudioManager.isSpeakerphoneOn - savedIsMicrophoneMute = androidAudioManager.isMicrophoneMute - hasWiredHeadset = androidAudioManager.isWiredHeadsetOn + audioDevices.clear() - androidAudioManager.requestCallAudioFocus() + signalBluetoothManager.start() - setMicrophoneMute(false) + updateAudioDeviceState() - audioDevices.clear() + wiredHeadsetReceiver = WiredHeadsetReceiver() + context.registerReceiver(wiredHeadsetReceiver, IntentFilter(AudioManager.ACTION_HEADSET_PLUG)) - signalBluetoothManager!!.start() + state = State.PREINITIALIZED - updateAudioDeviceState() + Log.d(TAG, "Initialized") + } + } - wiredHeadsetReceiver = WiredHeadsetReceiver() - context.registerReceiver(wiredHeadsetReceiver, IntentFilter(AudioManager.ACTION_HEADSET_PLUG)) - - state = State.PREINITIALIZED - - Log.d(TAG, "Initialized") + fun shutdown() { + handler.post { + stop(false) + if (commandAndControlThread != null) { + Log.i(TAG, "Shutting down command and control") + commandAndControlThread?.quitSafely() + commandAndControlThread = null } } } @@ -138,23 +139,11 @@ class SignalAudioManager(private val context: Context, private fun stop(playDisconnect: Boolean) { Log.d(TAG, "Stopping. state: $state") - if (state == State.UNINITIALIZED) { - Log.i(TAG, "Trying to stop AudioManager in incorrect state: $state") - return - } - handler?.post { - incomingRinger.stop() - outgoingRinger.stop() - stop(false) - if (commandAndControlThread != null) { - Log.i(TAG, "Shutting down command and control") - commandAndControlThread?.quitSafely() - commandAndControlThread = null - } - } + incomingRinger.stop() + outgoingRinger.stop() - if (playDisconnect) { + if (playDisconnect && state != State.UNINITIALIZED) { val volume: Float = androidAudioManager.ringVolumeWithMinimum() soundPool.play(disconnectedSoundId, volume, volume, 0, 0, 1.0f) } @@ -170,7 +159,7 @@ class SignalAudioManager(private val context: Context, } wiredHeadsetReceiver = null - signalBluetoothManager?.stop() + signalBluetoothManager.stop() setSpeakerphoneOn(savedIsSpeakerPhoneOn) setMicrophoneMute(savedIsMicrophoneMute) @@ -183,25 +172,25 @@ class SignalAudioManager(private val context: Context, } private fun updateAudioDeviceState() { - handler!!.assertHandlerThread() + handler.assertHandlerThread() Log.i( TAG, "updateAudioDeviceState(): " + "wired: $hasWiredHeadset " + - "bt: ${signalBluetoothManager!!.state} " + + "bt: ${signalBluetoothManager.state} " + "available: $audioDevices " + "selected: $selectedAudioDevice " + "userSelected: $userSelectedAudioDevice" ) - if (signalBluetoothManager!!.state.shouldUpdate()) { - signalBluetoothManager!!.updateDevice() + if (signalBluetoothManager.state.shouldUpdate()) { + signalBluetoothManager.updateDevice() } val newAudioDevices = mutableSetOf(AudioDevice.SPEAKER_PHONE) - if (signalBluetoothManager!!.state.hasDevice()) { + if (signalBluetoothManager.state.hasDevice()) { newAudioDevices += AudioDevice.BLUETOOTH } @@ -217,7 +206,7 @@ class SignalAudioManager(private val context: Context, var audioDeviceSetUpdated = audioDevices != newAudioDevices audioDevices = newAudioDevices - if (signalBluetoothManager!!.state == BState.UNAVAILABLE && userSelectedAudioDevice == AudioDevice.BLUETOOTH) { + if (signalBluetoothManager.state == BState.UNAVAILABLE && userSelectedAudioDevice == AudioDevice.BLUETOOTH) { userSelectedAudioDevice = AudioDevice.NONE } @@ -230,7 +219,7 @@ class SignalAudioManager(private val context: Context, userSelectedAudioDevice = AudioDevice.NONE } - val btState = signalBluetoothManager!!.state + val btState = signalBluetoothManager.state val needBluetoothAudioStart = btState == BState.AVAILABLE && (userSelectedAudioDevice == AudioDevice.NONE || userSelectedAudioDevice == AudioDevice.BLUETOOTH || autoSwitchToBluetooth) @@ -238,27 +227,27 @@ class SignalAudioManager(private val context: Context, (userSelectedAudioDevice != AudioDevice.NONE && userSelectedAudioDevice != AudioDevice.BLUETOOTH) if (btState.hasDevice()) { - Log.i(TAG, "Need bluetooth audio: state: ${signalBluetoothManager!!.state} start: $needBluetoothAudioStart stop: $needBluetoothAudioStop") + Log.i(TAG, "Need bluetooth audio: state: ${signalBluetoothManager.state} start: $needBluetoothAudioStart stop: $needBluetoothAudioStop") } if (needBluetoothAudioStop) { - signalBluetoothManager!!.stopScoAudio() - signalBluetoothManager!!.updateDevice() + signalBluetoothManager.stopScoAudio() + signalBluetoothManager.updateDevice() } - if (!autoSwitchToBluetooth && signalBluetoothManager!!.state == BState.UNAVAILABLE) { + if (!autoSwitchToBluetooth && signalBluetoothManager.state == BState.UNAVAILABLE) { autoSwitchToBluetooth = true } - if (needBluetoothAudioStart && !needBluetoothAudioStop) { - if (!signalBluetoothManager!!.startScoAudio()) { + if (!needBluetoothAudioStop && needBluetoothAudioStart) { + if (!signalBluetoothManager.startScoAudio()) { Log.e(TAG,"Failed to start sco audio") audioDevices.remove(AudioDevice.BLUETOOTH) audioDeviceSetUpdated = true } } - if (autoSwitchToBluetooth && signalBluetoothManager!!.state == BState.CONNECTED) { + if (autoSwitchToBluetooth && signalBluetoothManager.state == BState.CONNECTED) { userSelectedAudioDevice = AudioDevice.BLUETOOTH autoSwitchToBluetooth = false } @@ -373,7 +362,7 @@ class SignalAudioManager(private val context: Context, val pluggedIn = intent.getIntExtra("state", 0) == 1 val hasMic = intent.getIntExtra("microphone", 0) == 1 - handler?.post { onWiredHeadsetChange(pluggedIn, hasMic) } + handler.post { onWiredHeadsetChange(pluggedIn, hasMic) } } } diff --git a/app/src/main/res/color/button_destructive.xml b/app/src/main/res/color/button_destructive.xml new file mode 100644 index 0000000000..cefbfed23a --- /dev/null +++ b/app/src/main/res/color/button_destructive.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/color/prominent_button_color.xml b/app/src/main/res/color/prominent_button_color.xml new file mode 100644 index 0000000000..8f2e692fda --- /dev/null +++ b/app/src/main/res/color/prominent_button_color.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/borderless_button_medium_background.xml b/app/src/main/res/drawable/borderless_button_medium_background.xml new file mode 100644 index 0000000000..6c72f9e72b --- /dev/null +++ b/app/src/main/res/drawable/borderless_button_medium_background.xml @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/app/src/main/res/drawable/conversation_pinned_background.xml b/app/src/main/res/drawable/conversation_pinned_background.xml index 104b9c272e..eb64dc7f5f 100644 --- a/app/src/main/res/drawable/conversation_pinned_background.xml +++ b/app/src/main/res/drawable/conversation_pinned_background.xml @@ -1,7 +1,7 @@ + android:color="?android:colorControlHighlight"> diff --git a/app/src/main/res/drawable/conversation_unread_background.xml b/app/src/main/res/drawable/conversation_unread_background.xml index de0f5fb688..9e9bb94361 100644 --- a/app/src/main/res/drawable/conversation_unread_background.xml +++ b/app/src/main/res/drawable/conversation_unread_background.xml @@ -1,7 +1,7 @@ + android:color="?android:colorControlHighlight"> diff --git a/app/src/main/res/drawable/conversation_view_background.xml b/app/src/main/res/drawable/conversation_view_background.xml index aaceb7ed54..2f177318e0 100644 --- a/app/src/main/res/drawable/conversation_view_background.xml +++ b/app/src/main/res/drawable/conversation_view_background.xml @@ -1,7 +1,7 @@ + android:color="?android:colorControlHighlight"> diff --git a/app/src/main/res/drawable/default_dialog_background_inset.xml b/app/src/main/res/drawable/default_dialog_background_inset.xml deleted file mode 100644 index 0ff315ebd3..0000000000 --- a/app/src/main/res/drawable/default_dialog_background_inset.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/destructive_dialog_text_button_background.xml b/app/src/main/res/drawable/destructive_dialog_text_button_background.xml index 1eff84a69b..f3e13c8000 100644 --- a/app/src/main/res/drawable/destructive_dialog_text_button_background.xml +++ b/app/src/main/res/drawable/destructive_dialog_text_button_background.xml @@ -1,11 +1,10 @@ - - - - - - - - \ No newline at end of file + + + + + + + + diff --git a/app/src/main/res/drawable/destructive_outline_button_medium_background.xml b/app/src/main/res/drawable/destructive_outline_button_medium_background.xml index 7db4da2ec4..c6e01ef98e 100644 --- a/app/src/main/res/drawable/destructive_outline_button_medium_background.xml +++ b/app/src/main/res/drawable/destructive_outline_button_medium_background.xml @@ -1,11 +1,13 @@ - - - - - - - - \ No newline at end of file + + + + + + + + + diff --git a/app/src/main/res/drawable/filled_button_medium_background.xml b/app/src/main/res/drawable/filled_button_medium_background.xml new file mode 100644 index 0000000000..10eb6de679 --- /dev/null +++ b/app/src/main/res/drawable/filled_button_medium_background.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_pictures.xml b/app/src/main/res/drawable/ic_pictures.xml new file mode 100644 index 0000000000..967d0a65b0 --- /dev/null +++ b/app/src/main/res/drawable/ic_pictures.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/app/src/main/res/drawable/mention_candidate_view_background.xml b/app/src/main/res/drawable/mention_candidate_view_background.xml index 7b179020aa..4e9785a41e 100644 --- a/app/src/main/res/drawable/mention_candidate_view_background.xml +++ b/app/src/main/res/drawable/mention_candidate_view_background.xml @@ -1,7 +1,7 @@ + android:color="?android:colorControlHighlight"> diff --git a/app/src/main/res/drawable/profile_picture_view_large_background.xml b/app/src/main/res/drawable/profile_picture_view_large_background.xml index 278d70901f..9b90660803 100644 --- a/app/src/main/res/drawable/profile_picture_view_large_background.xml +++ b/app/src/main/res/drawable/profile_picture_view_large_background.xml @@ -5,5 +5,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/prominent_filled_button_medium_background.xml b/app/src/main/res/drawable/prominent_filled_button_medium_background.xml index a06a0d11e5..698a67c0a9 100644 --- a/app/src/main/res/drawable/prominent_filled_button_medium_background.xml +++ b/app/src/main/res/drawable/prominent_filled_button_medium_background.xml @@ -1,11 +1,10 @@ - - - - - - - - \ No newline at end of file + + + + + + + + diff --git a/app/src/main/res/drawable/prominent_outline_button_medium_background.xml b/app/src/main/res/drawable/prominent_outline_button_medium_background.xml index ee3bec8f7f..4bde2f855c 100644 --- a/app/src/main/res/drawable/prominent_outline_button_medium_background.xml +++ b/app/src/main/res/drawable/prominent_outline_button_medium_background.xml @@ -1,11 +1,13 @@ - - - - - - - - \ No newline at end of file + + + + + + + + + diff --git a/app/src/main/res/drawable/setting_button_background.xml b/app/src/main/res/drawable/setting_button_background.xml index aaceb7ed54..2f177318e0 100644 --- a/app/src/main/res/drawable/setting_button_background.xml +++ b/app/src/main/res/drawable/setting_button_background.xml @@ -1,7 +1,7 @@ + android:color="?android:colorControlHighlight"> diff --git a/app/src/main/res/drawable/unimportant_dialog_text_button_background.xml b/app/src/main/res/drawable/unimportant_dialog_text_button_background.xml index 1eff84a69b..f3e13c8000 100644 --- a/app/src/main/res/drawable/unimportant_dialog_text_button_background.xml +++ b/app/src/main/res/drawable/unimportant_dialog_text_button_background.xml @@ -1,11 +1,10 @@ - - - - - - - - \ No newline at end of file + + + + + + + + diff --git a/app/src/main/res/drawable/unimportant_outline_button_medium_background.xml b/app/src/main/res/drawable/unimportant_outline_button_medium_background.xml index 6e0de35a5b..d12f7408d9 100644 --- a/app/src/main/res/drawable/unimportant_outline_button_medium_background.xml +++ b/app/src/main/res/drawable/unimportant_outline_button_medium_background.xml @@ -1,11 +1,13 @@ - - - - - - - - \ No newline at end of file + + + + + + + + + diff --git a/app/src/main/res/drawable/view_separator.xml b/app/src/main/res/drawable/view_separator.xml new file mode 100644 index 0000000000..27dd4bc967 --- /dev/null +++ b/app/src/main/res/drawable/view_separator.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-sw400dp/activity_landing.xml b/app/src/main/res/layout-sw400dp/activity_landing.xml index 1e89cd967d..5e5a36704a 100644 --- a/app/src/main/res/layout-sw400dp/activity_landing.xml +++ b/app/src/main/res/layout-sw400dp/activity_landing.xml @@ -52,6 +52,7 @@ android:text="@string/activity_landing_restore_button_title" />