diff --git a/protobuf/Backups.proto b/protobuf/Backups.proto
index df62b5ae40..054c3526ef 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 16135c7e8e..9f05c310a0 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 b0a418338b..56aeed0361 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 7366c56619..af8d1ef57b 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 0b81eb1c58..138707b3ca 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 8f17c786bb..f16e44d504 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 ed505f4973..7aa0500cc8 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 49d07244f2..8ff17b3518 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();
}