From d8d94407c6ee9d022c52c293f045a77cc7f37b13 Mon Sep 17 00:00:00 2001
From: Ehren Kret <ehren@signal.org>
Date: Mon, 21 Jun 2021 14:13:51 -0500
Subject: [PATCH] Create announcement group capability

---
 .../controllers/DeviceController.java         | 10 ++---
 .../entities/UserCapabilities.java            | 13 +++++-
 .../textsecuregcm/storage/Account.java        |  6 +++
 .../textsecuregcm/storage/Device.java         | 10 ++++-
 .../storage/AccountsDynamoDbTest.java         |  2 +-
 .../textsecuregcm/storage/DeviceTest.java     |  2 +-
 .../controllers/DeviceControllerTest.java     | 37 ++++++++++++++---
 .../controllers/MessageControllerTest.java    |  8 ++--
 .../controllers/ProfileControllerTest.java    |  4 ++
 .../tests/storage/AccountTest.java            | 41 ++++++++++++++++---
 .../tests/storage/AccountsTest.java           |  2 +-
 11 files changed, 107 insertions(+), 28 deletions(-)

diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/DeviceController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/DeviceController.java
index a0cd2358d..8b42f8efb 100644
--- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/DeviceController.java
+++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/DeviceController.java
@@ -234,13 +234,9 @@ public class DeviceController {
   private boolean isCapabilityDowngrade(Account account, DeviceCapabilities capabilities, String userAgent) {
     boolean isDowngrade = false;
 
-    if (account.isSenderKeySupported() && !capabilities.isSenderKey()) {
-      isDowngrade = true;
-    }
-
-    if (account.isGv1MigrationSupported() && !capabilities.isGv1Migration()) {
-      isDowngrade = true;
-    }
+    isDowngrade |= account.isAnnouncementGroupSupported() && !capabilities.isAnnouncementGroup();
+    isDowngrade |= account.isSenderKeySupported() && !capabilities.isSenderKey();
+    isDowngrade |= account.isGv1MigrationSupported() && !capabilities.isGv1Migration();
 
     if (account.isGroupsV2Supported()) {
       try {
diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/entities/UserCapabilities.java b/service/src/main/java/org/whispersystems/textsecuregcm/entities/UserCapabilities.java
index cce35e8ac..4431d856e 100644
--- a/service/src/main/java/org/whispersystems/textsecuregcm/entities/UserCapabilities.java
+++ b/service/src/main/java/org/whispersystems/textsecuregcm/entities/UserCapabilities.java
@@ -14,7 +14,8 @@ public class UserCapabilities {
     return new UserCapabilities(
         account.isGroupsV2Supported(),
         account.isGv1MigrationSupported(),
-        account.isSenderKeySupported());
+        account.isSenderKeySupported(),
+        account.isAnnouncementGroupSupported());
   }
 
   @JsonProperty
@@ -26,12 +27,16 @@ public class UserCapabilities {
   @JsonProperty
   private boolean senderKey;
 
+  @JsonProperty
+  private boolean announcementGroup;
+
   public UserCapabilities() {}
 
-  public UserCapabilities(boolean gv2, boolean gv1Migration, final boolean senderKey) {
+  public UserCapabilities(boolean gv2, boolean gv1Migration, final boolean senderKey, final boolean announcementGroup) {
     this.gv2  = gv2;
     this.gv1Migration = gv1Migration;
     this.senderKey = senderKey;
+    this.announcementGroup = announcementGroup;
   }
 
   public boolean isGv2() {
@@ -45,4 +50,8 @@ public class UserCapabilities {
   public boolean isSenderKey() {
     return senderKey;
   }
+
+  public boolean isAnnouncementGroup() {
+    return announcementGroup;
+  }
 }
diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java
index 3dbb3c3d5..fdebdf5ad 100644
--- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java
+++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Account.java
@@ -151,6 +151,12 @@ public class Account implements Principal  {
         .allMatch(device -> device.getCapabilities() != null && device.getCapabilities().isSenderKey());
   }
 
+  public boolean isAnnouncementGroupSupported() {
+    return devices.stream()
+        .filter(Device::isEnabled)
+        .allMatch(device -> device.getCapabilities() != null && device.getCapabilities().isAnnouncementGroup());
+  }
+
   public boolean isEnabled() {
     return getMasterDevice().map(Device::isEnabled).orElse(false);
   }
diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Device.java b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Device.java
index 0ef120634..1e63ee40f 100644
--- a/service/src/main/java/org/whispersystems/textsecuregcm/storage/Device.java
+++ b/service/src/main/java/org/whispersystems/textsecuregcm/storage/Device.java
@@ -276,10 +276,13 @@ public class Device {
     @JsonProperty
     private boolean senderKey;
 
+    @JsonProperty
+    private boolean announcementGroup;
+
     public DeviceCapabilities() {}
 
     public DeviceCapabilities(boolean gv2, final boolean gv2_2, final boolean gv2_3, boolean storage, boolean transfer,
-        boolean gv1Migration, final boolean senderKey) {
+        boolean gv1Migration, final boolean senderKey, final boolean announcementGroup) {
       this.gv2 = gv2;
       this.gv2_2 = gv2_2;
       this.gv2_3 = gv2_3;
@@ -287,6 +290,7 @@ public class Device {
       this.transfer = transfer;
       this.gv1Migration = gv1Migration;
       this.senderKey = senderKey;
+      this.announcementGroup = announcementGroup;
     }
 
     public boolean isGv2() {
@@ -316,5 +320,9 @@ public class Device {
     public boolean isSenderKey() {
       return senderKey;
     }
+
+    public boolean isAnnouncementGroup() {
+      return announcementGroup;
+    }
   }
 }
diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsDynamoDbTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsDynamoDbTest.java
index 42e2fb8a3..6780e42ab 100644
--- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsDynamoDbTest.java
+++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/AccountsDynamoDbTest.java
@@ -423,7 +423,7 @@ class AccountsDynamoDbTest {
     SignedPreKey signedPreKey = new SignedPreKey(random.nextInt(), "testPublicKey-" + random.nextInt(), "testSignature-" + random.nextInt());
     return new Device(id, "testName-" + random.nextInt(), "testAuthToken-" + random.nextInt(), "testSalt-" + random.nextInt(),
         "testGcmId-" + random.nextInt(), "testApnId-" + random.nextInt(), "testVoipApnId-" + random.nextInt(), random.nextBoolean(), random.nextInt(), signedPreKey, random.nextInt(), random.nextInt(), "testUserAgent-" + random.nextInt() , 0, new Device.DeviceCapabilities(random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(),
-        false));
+        false, false));
   }
 
   private Account generateAccount(String number, UUID uuid) {
diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/storage/DeviceTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/storage/DeviceTest.java
index 4ba27cb09..2a123d0d9 100644
--- a/service/src/test/java/org/whispersystems/textsecuregcm/storage/DeviceTest.java
+++ b/service/src/test/java/org/whispersystems/textsecuregcm/storage/DeviceTest.java
@@ -70,7 +70,7 @@ public class DeviceTest {
     @Parameters(method = "argumentsForTestIsGroupsV2Supported")
     public void testIsGroupsV2Supported(final boolean master, final String apnId, final boolean gv2Capability, final boolean gv2_2Capability, final boolean gv2_3Capability, final boolean expectGv2Supported) {
         final Device.DeviceCapabilities capabilities = new Device.DeviceCapabilities(gv2Capability, gv2_2Capability, gv2_3Capability, false, false, false,
-            false);
+            false, false);
         final Device                    device       = new Device(master ? 1 : 2, "test", "auth-token", "salt",
             null, apnId, null, false, 1, null, 0, 0, "user-agent", 0, capabilities);
 
diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DeviceControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DeviceControllerTest.java
index af871d26c..ba2afd294 100644
--- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DeviceControllerTest.java
+++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/DeviceControllerTest.java
@@ -116,6 +116,7 @@ public class DeviceControllerTest {
     when(account.isGroupsV2Supported()).thenReturn(true);
     when(account.isGv1MigrationSupported()).thenReturn(true);
     when(account.isSenderKeySupported()).thenReturn(true);
+    when(account.isAnnouncementGroupSupported()).thenReturn(true);
 
     when(pendingDevicesManager.getCodeForNumber(AuthHelper.VALID_NUMBER)).thenReturn(Optional.of(new StoredVerificationCode("5678901", System.currentTimeMillis(), null)));
     when(pendingDevicesManager.getCodeForNumber(AuthHelper.VALID_NUMBER_TWO)).thenReturn(Optional.of(new StoredVerificationCode("1112223", System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(31), null)));
@@ -223,7 +224,7 @@ public class DeviceControllerTest {
   @Test
   @Parameters(method = "argumentsForDeviceDowngradeCapabilitiesTest")
   public void deviceDowngradeCapabilitiesTest(final String userAgent, final boolean gv2, final boolean gv2_2, final boolean gv2_3, final int expectedStatus) throws Exception {
-    DeviceCapabilities deviceCapabilities = new DeviceCapabilities(gv2, gv2_2, gv2_3, true, false, true, true);
+    DeviceCapabilities deviceCapabilities = new DeviceCapabilities(gv2, gv2_2, gv2_3, true, false, true, true, true);
     AccountAttributes accountAttributes = new AccountAttributes(false, 1234, null, null, null, true, deviceCapabilities);
     Response response = resources.getJerseyTest()
             .target("/v1/devices/5678901")
@@ -263,7 +264,7 @@ public class DeviceControllerTest {
 
   @Test
   public void deviceDowngradeGv1MigrationTest() {
-    DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true, false, false, true);
+    DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true, false, false, true, true);
     AccountAttributes accountAttributes = new AccountAttributes(false, 1234, null, null, null, true, deviceCapabilities);
     Response response = resources.getJerseyTest()
                                  .target("/v1/devices/5678901")
@@ -274,7 +275,7 @@ public class DeviceControllerTest {
 
     assertThat(response.getStatus()).isEqualTo(409);
 
-    deviceCapabilities = new DeviceCapabilities(true, true, true, true, false, true, true);
+    deviceCapabilities = new DeviceCapabilities(true, true, true, true, false, true, true, true);
     accountAttributes = new AccountAttributes(false, 1234, null, null, null, true, deviceCapabilities);
     response = resources.getJerseyTest()
                         .target("/v1/devices/5678901")
@@ -288,7 +289,7 @@ public class DeviceControllerTest {
 
   @Test
   public void deviceDowngradeSenderKeyTest() {
-    DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, false);
+    DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, false, true);
     AccountAttributes accountAttributes =
         new AccountAttributes(false, 1234, null, null, null, true, deviceCapabilities);
     Response response = resources
@@ -300,7 +301,33 @@ public class DeviceControllerTest {
         .put(Entity.entity(accountAttributes, MediaType.APPLICATION_JSON_TYPE));
     assertThat(response.getStatus()).isEqualTo(409);
 
-    deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true);
+    deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true);
+    accountAttributes = new AccountAttributes(false, 1234, null, null, null, true, deviceCapabilities);
+    response = resources
+        .getJerseyTest()
+        .target("/v1/devices/5678901")
+        .request()
+        .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_NUMBER, AuthHelper.VALID_PASSWORD))
+        .header("User-Agent", "Signal-Android/5.42.8675309 Android/30")
+        .put(Entity.entity(accountAttributes, MediaType.APPLICATION_JSON_TYPE));
+    assertThat(response.getStatus()).isEqualTo(200);
+  }
+
+  @Test
+  public void deviceDowngradeAnnouncementGroupTest() {
+    DeviceCapabilities deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, false);
+    AccountAttributes accountAttributes =
+        new AccountAttributes(false, 1234, null, null, null, true, deviceCapabilities);
+    Response response = resources
+        .getJerseyTest()
+        .target("/v1/devices/5678901")
+        .request()
+        .header("Authorization", AuthHelper.getAuthHeader(AuthHelper.VALID_NUMBER, AuthHelper.VALID_PASSWORD))
+        .header("User-Agent", "Signal-Android/5.42.8675309 Android/30")
+        .put(Entity.entity(accountAttributes, MediaType.APPLICATION_JSON_TYPE));
+    assertThat(response.getStatus()).isEqualTo(409);
+
+    deviceCapabilities = new DeviceCapabilities(true, true, true, true, true, true, true, true);
     accountAttributes = new AccountAttributes(false, 1234, null, null, null, true, deviceCapabilities);
     response = resources
         .getJerseyTest()
diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/MessageControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/MessageControllerTest.java
index 71b336f10..b0933f429 100644
--- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/MessageControllerTest.java
+++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/MessageControllerTest.java
@@ -157,19 +157,19 @@ class MessageControllerTest {
     Set<Device> singleDeviceList = new HashSet<Device>() {{
       add(new Device(1, null, "foo", "bar",
           "isgcm", null, null, false, 111, new SignedPreKey(333, "baz", "boop"), System.currentTimeMillis(), System.currentTimeMillis(), "Test", 0, new Device.DeviceCapabilities(true, false, false, true, true, false,
-          false)));
+          false, false)));
     }};
 
     Set<Device> multiDeviceList = new HashSet<Device>() {{
       add(new Device(1, null, "foo", "bar",
           "isgcm", null, null, false, 222, new SignedPreKey(111, "foo", "bar"), System.currentTimeMillis(), System.currentTimeMillis(), "Test", 0, new Device.DeviceCapabilities(true, false, false, true, false, false,
-          false)));
+          false, false)));
       add(new Device(2, null, "foo", "bar",
           "isgcm", null, null, false, 333, new SignedPreKey(222, "oof", "rab"), System.currentTimeMillis(), System.currentTimeMillis(), "Test", 0, new Device.DeviceCapabilities(true, false, false, true, false, false,
-          false)));
+          false, false)));
       add(new Device(3, null, "foo", "bar",
           "isgcm", null, null, false, 444, null, System.currentTimeMillis() - TimeUnit.DAYS.toMillis(31), System.currentTimeMillis(), "Test", 0, new Device.DeviceCapabilities(false, false, false, false, false, false,
-          false)));
+          false, false)));
     }};
 
     Account singleDeviceAccount  = new Account(SINGLE_DEVICE_RECIPIENT, SINGLE_DEVICE_UUID, singleDeviceList, "1234".getBytes());
diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/ProfileControllerTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/ProfileControllerTest.java
index a9217bec9..34898c3d1 100644
--- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/ProfileControllerTest.java
+++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/controllers/ProfileControllerTest.java
@@ -125,6 +125,7 @@ public class ProfileControllerTest {
     when(profileAccount.isGroupsV2Supported()).thenReturn(false);
     when(profileAccount.isGv1MigrationSupported()).thenReturn(false);
     when(profileAccount.isSenderKeySupported()).thenReturn(false);
+    when(profileAccount.isAnnouncementGroupSupported()).thenReturn(false);
     when(profileAccount.getCurrentProfileVersion()).thenReturn(Optional.empty());
 
     Account capabilitiesAccount = mock(Account.class);
@@ -136,6 +137,7 @@ public class ProfileControllerTest {
     when(capabilitiesAccount.isGroupsV2Supported()).thenReturn(true);
     when(capabilitiesAccount.isGv1MigrationSupported()).thenReturn(true);
     when(capabilitiesAccount.isSenderKeySupported()).thenReturn(true);
+    when(capabilitiesAccount.isAnnouncementGroupSupported()).thenReturn(true);
 
     when(accountsManager.get(AuthHelper.VALID_NUMBER_TWO)).thenReturn(Optional.of(profileAccount));
     when(accountsManager.get(AuthHelper.VALID_UUID_TWO)).thenReturn(Optional.of(profileAccount));
@@ -274,6 +276,7 @@ public class ProfileControllerTest {
     assertThat(profile.getCapabilities().isGv2()).isTrue();
     assertThat(profile.getCapabilities().isGv1Migration()).isTrue();
     assertThat(profile.getCapabilities().isSenderKey()).isTrue();
+    assertThat(profile.getCapabilities().isAnnouncementGroup()).isTrue();
 
     profile = resources
         .getJerseyTest()
@@ -285,6 +288,7 @@ public class ProfileControllerTest {
     assertThat(profile.getCapabilities().isGv2()).isFalse();
     assertThat(profile.getCapabilities().isGv1Migration()).isFalse();
     assertThat(profile.getCapabilities().isSenderKey()).isFalse();
+    assertThat(profile.getCapabilities().isAnnouncementGroup()).isFalse();
   }
 
   @Test
diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/storage/AccountTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/storage/AccountTest.java
index ebdc3659e..e3601f4a2 100644
--- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/storage/AccountTest.java
+++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/storage/AccountTest.java
@@ -43,6 +43,10 @@ public class AccountTest {
   private final Device senderKeyIncapableDevice = mock(Device.class);
   private final Device senderKeyIncapableExpiredDevice = mock(Device.class);
 
+  private final Device announcementGroupCapableDevice = mock(Device.class);
+  private final Device announcementGroupIncapableDevice = mock(Device.class);
+  private final Device announcementGroupIncapableExpiredDevice = mock(Device.class);
+
   @Before
   public void setup() {
     when(oldMasterDevice.getLastSeen()).thenReturn(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(366));
@@ -78,28 +82,40 @@ public class AccountTest {
     when(gv2IncapableExpiredDevice.isEnabled()).thenReturn(false);
 
     when(gv1MigrationCapableDevice.getCapabilities()).thenReturn(
-        new DeviceCapabilities(true, true, true, true, true, true, false));
+        new DeviceCapabilities(true, true, true, true, true, true, false, false));
     when(gv1MigrationCapableDevice.isEnabled()).thenReturn(true);
 
     when(gv1MigrationIncapableDevice.getCapabilities()).thenReturn(
-        new DeviceCapabilities(true, true, true, true, true, false, false));
+        new DeviceCapabilities(true, true, true, true, true, false, false, false));
     when(gv1MigrationIncapableDevice.isEnabled()).thenReturn(true);
 
     when(gv1MigrationIncapableExpiredDevice.getCapabilities()).thenReturn(
-        new DeviceCapabilities(true, true, true, true, true, false, false));
+        new DeviceCapabilities(true, true, true, true, true, false, false, false));
     when(gv1MigrationIncapableExpiredDevice.isEnabled()).thenReturn(false);
 
     when(senderKeyCapableDevice.getCapabilities()).thenReturn(
-        new DeviceCapabilities(true, true, true, true, true, true, true));
+        new DeviceCapabilities(true, true, true, true, true, true, true, false));
     when(senderKeyCapableDevice.isEnabled()).thenReturn(true);
 
     when(senderKeyIncapableDevice.getCapabilities()).thenReturn(
-        new DeviceCapabilities(true, true, true, true, true, true, false));
+        new DeviceCapabilities(true, true, true, true, true, true, false, false));
     when(senderKeyIncapableDevice.isEnabled()).thenReturn(true);
 
     when(senderKeyIncapableExpiredDevice.getCapabilities()).thenReturn(
-        new DeviceCapabilities(true, true, true, true, true, true, false));
+        new DeviceCapabilities(true, true, true, true, true, true, false, false));
     when(senderKeyIncapableExpiredDevice.isEnabled()).thenReturn(false);
+
+    when(announcementGroupCapableDevice.getCapabilities()).thenReturn(
+        new DeviceCapabilities(true, true, true, true, true, true, true, true));
+    when(announcementGroupCapableDevice.isEnabled()).thenReturn(true);
+
+    when(announcementGroupIncapableDevice.getCapabilities()).thenReturn(
+        new DeviceCapabilities(true, true, true, true, true, true, true, false));
+    when(announcementGroupIncapableDevice.isEnabled()).thenReturn(true);
+
+    when(announcementGroupIncapableExpiredDevice.getCapabilities()).thenReturn(
+        new DeviceCapabilities(true, true, true, true, true, true, true, false));
+    when(announcementGroupIncapableExpiredDevice.isEnabled()).thenReturn(false);
   }
 
   @Test
@@ -233,4 +249,17 @@ public class AccountTest {
         Set.of(senderKeyCapableDevice, senderKeyIncapableExpiredDevice),
         "1234".getBytes(StandardCharsets.UTF_8)).isSenderKeySupported()).isTrue();
   }
+
+  @Test
+  public void isAnnouncementGroupSupported() {
+    assertThat(new Account("+18005551234", UUID.randomUUID(),
+        Set.of(announcementGroupCapableDevice),
+        "1234".getBytes(StandardCharsets.UTF_8)).isAnnouncementGroupSupported()).isTrue();
+    assertThat(new Account("+18005551234", UUID.randomUUID(),
+        Set.of(announcementGroupCapableDevice, announcementGroupIncapableDevice),
+        "1234".getBytes(StandardCharsets.UTF_8)).isAnnouncementGroupSupported()).isFalse();
+    assertThat(new Account("+18005551234", UUID.randomUUID(),
+        Set.of(announcementGroupCapableDevice, announcementGroupIncapableExpiredDevice),
+        "1234".getBytes(StandardCharsets.UTF_8)).isAnnouncementGroupSupported()).isTrue();
+  }
 }
diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/tests/storage/AccountsTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/tests/storage/AccountsTest.java
index 9c70c3b69..3b91acbc8 100644
--- a/service/src/test/java/org/whispersystems/textsecuregcm/tests/storage/AccountsTest.java
+++ b/service/src/test/java/org/whispersystems/textsecuregcm/tests/storage/AccountsTest.java
@@ -318,7 +318,7 @@ public class AccountsTest {
     SignedPreKey signedPreKey = new SignedPreKey(random.nextInt(), "testPublicKey-" + random.nextInt(), "testSignature-" + random.nextInt());
     return new Device(id, "testName-" + random.nextInt(), "testAuthToken-" + random.nextInt(), "testSalt-" + random.nextInt(),
         "testGcmId-" + random.nextInt(), "testApnId-" + random.nextInt(), "testVoipApnId-" + random.nextInt(), random.nextBoolean(), random.nextInt(), signedPreKey, random.nextInt(), random.nextInt(), "testUserAgent-" + random.nextInt() , 0, new Device.DeviceCapabilities(random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(), random.nextBoolean(),
-        false));
+        false, false));
   }
 
   private Account generateAccount(String number, UUID uuid) {
-- 
GitLab