diff --git a/protobuf/Backups.proto b/protobuf/Backups.proto index df62b5ae4..054c3526e 100644 --- a/protobuf/Backups.proto +++ b/protobuf/Backups.proto @@ -34,6 +34,11 @@ message Attachment { optional uint32 length = 3; } +message Avatar { + optional string name = 1; + optional uint32 length = 2; +} + message DatabaseVersion { optional uint32 version = 1; } @@ -50,4 +55,5 @@ message BackupFrame { optional Attachment attachment = 4; optional DatabaseVersion version = 5; optional bool end = 6; + optional Avatar avatar = 7; } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java index 16135c7e8..9f05c310a 100644 --- a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java +++ b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java @@ -187,6 +187,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi private void setHeader(@NonNull Recipient recipient) { glideRequests.load(recipient.getContactPhoto()) .fallback(recipient.getFallbackContactPhoto().asCallCard(this)) + .error(recipient.getFallbackContactPhoto().asCallCard(this)) .diskCacheStrategy(DiskCacheStrategy.ALL) .into(this.avatar); diff --git a/src/org/thoughtcrime/securesms/backup/BackupProtos.java b/src/org/thoughtcrime/securesms/backup/BackupProtos.java index b0a418338..56aeed036 100644 --- a/src/org/thoughtcrime/securesms/backup/BackupProtos.java +++ b/src/org/thoughtcrime/securesms/backup/BackupProtos.java @@ -2980,6 +2980,558 @@ public final class BackupProtos { // @@protoc_insertion_point(class_scope:signal.Attachment) } + 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 { @@ -3941,6 +4493,20 @@ public final class BackupProtos { * 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(); } /** * Protobuf type {@code signal.BackupFrame} @@ -4063,6 +4629,19 @@ public final class BackupProtos { 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; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { @@ -4229,6 +4808,28 @@ public final class BackupProtos { 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_; + } + private void initFields() { header_ = org.thoughtcrime.securesms.backup.BackupProtos.Header.getDefaultInstance(); statement_ = org.thoughtcrime.securesms.backup.BackupProtos.SqlStatement.getDefaultInstance(); @@ -4236,6 +4837,7 @@ public final class BackupProtos { 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(); } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -4267,6 +4869,9 @@ public final class BackupProtos { if (((bitField0_ & 0x00000020) == 0x00000020)) { output.writeBool(6, end_); } + if (((bitField0_ & 0x00000040) == 0x00000040)) { + output.writeMessage(7, avatar_); + } getUnknownFields().writeTo(output); } @@ -4300,6 +4905,10 @@ public final class BackupProtos { size += com.google.protobuf.CodedOutputStream .computeBoolSize(6, end_); } + if (((bitField0_ & 0x00000040) == 0x00000040)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(7, avatar_); + } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -4413,6 +5022,7 @@ public final class BackupProtos { getPreferenceFieldBuilder(); getAttachmentFieldBuilder(); getVersionFieldBuilder(); + getAvatarFieldBuilder(); } } private static Builder create() { @@ -4453,6 +5063,12 @@ public final class BackupProtos { 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); return this; } @@ -4525,6 +5141,14 @@ public final class BackupProtos { 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(); + } result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -4559,6 +5183,9 @@ public final class BackupProtos { if (other.hasEnd()) { setEnd(other.getEnd()); } + if (other.hasAvatar()) { + mergeAvatar(other.getAvatar()); + } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -5204,6 +5831,123 @@ public final class BackupProtos { 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_; + } + // @@protoc_insertion_point(builder_scope:signal.BackupFrame) } @@ -5235,6 +5979,11 @@ public final class BackupProtos { private static com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_signal_Attachment_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 @@ -5268,16 +6017,18 @@ public final class BackupProtos { "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\017DatabaseVersion", + "\002 \001(\004\022\016\n\006length\030\003 \001(\r\"&\n\006Avatar\022\014\n\004name\030", + "\001 \001(\t\022\016\n\006length\030\002 \001(\r\"\"\n\017DatabaseVersion" + "\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\"\343\001\n\013BackupFrame\022\036\n\006header\030" + + "\014\n\004salt\030\002 \001(\014\"\203\002\n\013BackupFrame\022\036\n\006header\030" + "\001 \001(\0132\016.signal.Header\022\'\n\tstatement\030\002 \001(\013" + "2\024.signal.SqlStatement\022,\n\npreference\030\003 \001" + "(\0132\030.signal.SharedPreference\022&\n\nattachme" + "nt\030\004 \001(\0132\022.signal.Attachment\022(\n\007version\030" + "\005 \001(\0132\027.signal.DatabaseVersion\022\013\n\003end\030\006 " + - "\001(\010B1\n!org.thoughtcrime.securesms.backup" + - "B\014BackupProtos" + "\001(\010\022\036\n\006avatar\030\007 \001(\0132\016.signal.AvatarB1\n!o" + + "rg.thoughtcrime.securesms.backupB\014Backup", + "Protos" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -5308,24 +6059,30 @@ public final class BackupProtos { com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_signal_Attachment_descriptor, new java.lang.String[] { "RowId", "AttachmentId", "Length", }); - internal_static_signal_DatabaseVersion_descriptor = + internal_static_signal_Avatar_descriptor = getDescriptor().getMessageTypes().get(3); + 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(4); 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(4); + getDescriptor().getMessageTypes().get(5); 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(5); + getDescriptor().getMessageTypes().get(6); 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", }); + new java.lang.String[] { "Header", "Statement", "Preference", "Attachment", "Version", "End", "Avatar", }); return null; } }; diff --git a/src/org/thoughtcrime/securesms/backup/FullBackupExporter.java b/src/org/thoughtcrime/securesms/backup/FullBackupExporter.java index 7366c5661..af8d1ef57 100644 --- a/src/org/thoughtcrime/securesms/backup/FullBackupExporter.java +++ b/src/org/thoughtcrime/securesms/backup/FullBackupExporter.java @@ -20,6 +20,7 @@ import org.thoughtcrime.securesms.crypto.AttachmentSecret; import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream; +import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.AttachmentDatabase; import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.database.MmsSmsColumns; @@ -27,12 +28,14 @@ import org.thoughtcrime.securesms.database.OneTimePreKeyDatabase; import org.thoughtcrime.securesms.database.SessionDatabase; import org.thoughtcrime.securesms.database.SignedPreKeyDatabase; import org.thoughtcrime.securesms.database.SmsDatabase; +import org.thoughtcrime.securesms.profiles.AvatarHelper; import org.thoughtcrime.securesms.util.Conversions; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.libsignal.kdf.HKDFv3; import org.whispersystems.libsignal.util.ByteUtil; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -87,6 +90,11 @@ public class FullBackupExporter extends FullBackupBase { outputStream.write(preference); } + for (File avatar : AvatarHelper.getAvatarFiles(context)) { + EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.PROGRESS, ++count)); + outputStream.write(avatar.getName(), new FileInputStream(avatar), avatar.length()); + } + outputStream.writeEnd(); outputStream.close(); EventBus.getDefault().post(new BackupEvent(BackupEvent.Type.FINISHED, ++count)); @@ -245,6 +253,17 @@ public class FullBackupExporter extends FullBackupBase { write(outputStream, BackupProtos.BackupFrame.newBuilder().setStatement(statement).build()); } + public void write(@NonNull String avatarName, @NonNull InputStream in, long size) throws IOException { + write(outputStream, BackupProtos.BackupFrame.newBuilder() + .setAvatar(BackupProtos.Avatar.newBuilder() + .setName(avatarName) + .setLength(Util.toIntExact(size)) + .build()) + .build()); + + writeStream(in); + } + public void write(@NonNull AttachmentId attachmentId, @NonNull InputStream in, long size) throws IOException { write(outputStream, BackupProtos.BackupFrame.newBuilder() .setAttachment(BackupProtos.Attachment.newBuilder() @@ -254,7 +273,20 @@ public class FullBackupExporter extends FullBackupBase { .build()) .build()); + writeStream(in); + } + void writeDatabaseVersion(int version) throws IOException { + write(outputStream, BackupProtos.BackupFrame.newBuilder() + .setVersion(BackupProtos.DatabaseVersion.newBuilder().setVersion(version)) + .build()); + } + + void writeEnd() throws IOException { + write(outputStream, BackupProtos.BackupFrame.newBuilder().setEnd(true).build()); + } + + private void writeStream(@NonNull InputStream inputStream) throws IOException { try { Conversions.intToByteArray(iv, 0, counter++); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(cipherKey, "AES"), new IvParameterSpec(iv)); @@ -263,7 +295,7 @@ public class FullBackupExporter extends FullBackupBase { byte[] buffer = new byte[8192]; int read; - while ((read = in.read(buffer)) != -1) { + while ((read = inputStream.read(buffer)) != -1) { byte[] ciphertext = cipher.update(buffer, 0, read); if (ciphertext != null) { @@ -283,16 +315,6 @@ public class FullBackupExporter extends FullBackupBase { } } - void writeDatabaseVersion(int version) throws IOException { - write(outputStream, BackupProtos.BackupFrame.newBuilder() - .setVersion(BackupProtos.DatabaseVersion.newBuilder().setVersion(version)) - .build()); - } - - void writeEnd() throws IOException { - write(outputStream, BackupProtos.BackupFrame.newBuilder().setEnd(true).build()); - } - private void write(@NonNull OutputStream out, @NonNull BackupProtos.BackupFrame frame) throws IOException { try { Conversions.intToByteArray(iv, 0, counter++); diff --git a/src/org/thoughtcrime/securesms/backup/FullBackupImporter.java b/src/org/thoughtcrime/securesms/backup/FullBackupImporter.java index 0b81eb1c5..138707b3c 100644 --- a/src/org/thoughtcrime/securesms/backup/FullBackupImporter.java +++ b/src/org/thoughtcrime/securesms/backup/FullBackupImporter.java @@ -18,7 +18,9 @@ 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.Address; import org.thoughtcrime.securesms.database.AttachmentDatabase; +import org.thoughtcrime.securesms.profiles.AvatarHelper; import org.thoughtcrime.securesms.util.Conversions; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.libsignal.kdf.HKDFv3; @@ -26,6 +28,7 @@ import org.whispersystems.libsignal.util.ByteUtil; import java.io.File; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -68,6 +71,7 @@ public class FullBackupImporter extends FullBackupBase { else if (frame.hasStatement()) processStatement(db, frame.getStatement()); else if (frame.hasPreference()) processPreference(context, frame.getPreference()); else if (frame.hasAttachment()) processAttachment(context, attachmentSecret, db, frame.getAttachment(), inputStream); + else if (frame.hasAvatar()) processAvatar(context, frame.getAvatar(), inputStream); } db.setTransactionSuccessful(); @@ -117,6 +121,10 @@ public class FullBackupImporter extends FullBackupBase { new String[] {String.valueOf(attachment.getRowId()), String.valueOf(attachment.getAttachmentId())}); } + private static void processAvatar(@NonNull Context context, @NonNull BackupProtos.Avatar avatar, @NonNull BackupRecordInputStream inputStream) throws IOException { + inputStream.readAttachmentTo(new FileOutputStream(AvatarHelper.getAvatarFile(context, Address.fromExternal(context, avatar.getName()))), avatar.getLength()); + } + @SuppressLint("ApplySharedPref") private static void processPreference(@NonNull Context context, SharedPreference preference) { SharedPreferences preferences = context.getSharedPreferences(preference.getFile(), 0); diff --git a/src/org/thoughtcrime/securesms/components/AvatarImageView.java b/src/org/thoughtcrime/securesms/components/AvatarImageView.java index 8f17c786b..f16e44d50 100644 --- a/src/org/thoughtcrime/securesms/components/AvatarImageView.java +++ b/src/org/thoughtcrime/securesms/components/AvatarImageView.java @@ -51,6 +51,7 @@ public class AvatarImageView extends AppCompatImageView { if (recipient != null) { requestManager.load(recipient.getContactPhoto()) .fallback(recipient.getFallbackContactPhotoDrawable(getContext(), inverted)) + .error(recipient.getFallbackContactPhotoDrawable(getContext(), inverted)) .diskCacheStrategy(DiskCacheStrategy.ALL) .circleCrop() .into(this); diff --git a/src/org/thoughtcrime/securesms/components/webrtc/WebRtcCallScreen.java b/src/org/thoughtcrime/securesms/components/webrtc/WebRtcCallScreen.java index ed505f497..7aa0500cc 100644 --- a/src/org/thoughtcrime/securesms/components/webrtc/WebRtcCallScreen.java +++ b/src/org/thoughtcrime/securesms/components/webrtc/WebRtcCallScreen.java @@ -282,6 +282,7 @@ public class WebRtcCallScreen extends FrameLayout implements RecipientModifiedLi GlideApp.with(getContext().getApplicationContext()) .load(recipient.getContactPhoto()) .fallback(recipient.getFallbackContactPhoto().asCallCard(getContext())) + .error(recipient.getFallbackContactPhoto().asCallCard(getContext())) .diskCacheStrategy(DiskCacheStrategy.ALL) .into(this.photo); diff --git a/src/org/thoughtcrime/securesms/profiles/AvatarHelper.java b/src/org/thoughtcrime/securesms/profiles/AvatarHelper.java index 49d07244f..8ff17b351 100644 --- a/src/org/thoughtcrime/securesms/profiles/AvatarHelper.java +++ b/src/org/thoughtcrime/securesms/profiles/AvatarHelper.java @@ -5,6 +5,8 @@ import android.content.Context; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import com.annimon.stream.Stream; + import org.thoughtcrime.securesms.database.Address; import java.io.File; @@ -12,6 +14,8 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.LinkedList; +import java.util.List; public class AvatarHelper { @@ -23,6 +27,14 @@ public class AvatarHelper { return new FileInputStream(getAvatarFile(context, address)); } + public static List getAvatarFiles(@NonNull Context context) { + File avatarDirectory = new File(context.getFilesDir(), AVATAR_DIRECTORY); + File[] results = avatarDirectory.listFiles(); + + if (results == null) return new LinkedList<>(); + else return Stream.of(results).toList(); + } + public static void delete(@NonNull Context context, @NonNull Address address) { getAvatarFile(context, address).delete(); }