docs: OmemoElement createRatchetUpdateElement(OmemoManager.LoggedInOmemoManager managerGuard,
                                              OmemoDevice contactsDevice)
              throws InterruptedException, SmackException.NoResponseException, CorruptedOmemoKeyException,
              SmackException.NotConnectedException, CannotEstablishOmemoSessionException, NoSuchAlgorithmException,
              CryptoFailedException {
  
          OmemoManager manager = managerGuard.get();
          OmemoDevice userDevice = manager.getOwnDevice();
  
          if (contactsDevice.equals(userDevice)) {
              throw new IllegalArgumentException("\"Thou shall not update thy own ratchet!\" - William Shakespeare");
          }
  
          // Establish session if necessary
          if (!hasSession(userDevice, contactsDevice)) {
              buildFreshSessionWithDevice(manager.getConnection(), userDevice, contactsDevice);
          }
  
          // Generate fresh AES key and IV
          byte[] messageKey = OmemoMessageBuilder.generateKey(KEYTYPE, KEYLENGTH);
          byte[] iv = OmemoMessageBuilder.generateIv();
  
          // Create message builder
          OmemoMessageBuilder<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Sess, T_Addr, T_ECPub, T_Bundle, T_Ciph> builder;
          try {
              builder = new OmemoMessageBuilder<>(userDevice, gullibleTrustCallback, getOmemoRatchet(manager),
                      messageKey, iv, null);
          } catch (InvalidKeyException | InvalidAlgorithmParameterException | NoSuchPaddingException | BadPaddingException | UnsupportedEncodingException | IllegalBlockSizeException e) {
              throw new CryptoFailedException(e);
          }
  
          // Add recipient
          try {
              builder.addRecipient(contactsDevice);
          } catch (UndecidedOmemoIdentityException | UntrustedOmemoIdentityException e) {
              throw new AssertionError("Gullible Trust Callback reported undecided or untrusted device, " +
                      "even though it MUST NOT do that.");
          } catch (NoIdentityKeyException e) {
              throw new AssertionError("We MUST have an identityKey for " + contactsDevice + " since we built a session." + e);
          }
  
          // Note: We don't need to update our message counter for a ratchet update message.
  
          return builder.finish();
      }