// Path: lib-android/src/main/java/com/google/capillary/android/CapillaryHandler.java
// public interface CapillaryHandler {
// 
//   /**
//    * Provides the plaintext after decrypting a Capillary ciphertext.
//    *
//    * @param isAuthKey whether the decryption was done using a public key requiring authentication.
//    * @param data the plaintext.
//    * @param extra the extra parameter originally passed to {@link DecrypterManager}.
//    */
//   void handleData(boolean isAuthKey, byte[] data, Object extra);
// 
//   /**
//    * Provides the generated Capillary public key.
//    *
//    * @param isAuthKey whether the public key requires authentication.
//    * @param publicKey the public key.
//    * @param extra the extra parameter originally passed to {@link KeyManager}.
//    */
//   void handlePublicKey(boolean isAuthKey, byte[] publicKey, Object extra);
// 
//   /**
//    * Provides the Capillary public key that was generated as a result of a decryption error.
//    *
//    * @param isAuthKey whether the public key requires authentication.
//    * @param publicKey the public key.
//    * @param ciphertext the ciphertext that caused the decryption error.
//    * @param extra the extra parameter originally passed to {@link DecrypterManager}.
//    */
//   void handlePublicKey(boolean isAuthKey, byte[] publicKey, byte[] ciphertext, Object extra);
// 
//   /**
//    * Signals that a Capillary ciphertext was saved to be decrypted after user authentication.
//    *
//    * @param ciphertext the saved Capillary ciphertext.
//    * @param extra the extra parameter originally passed to {@link DecrypterManager}.
//    */
//   void authCiphertextSavedForLater(byte[] ciphertext, Object extra);
// 
//   /**
//    * Signals that an error has occurred.
//    *
//    * @param errorCode the error code enum.
//    * @param ciphertext the Capillary ciphertext that is affected by this error.
//    * @param extra the extra parameter originally passed to {@link DecrypterManager}.
//    */
//   void error(CapillaryHandlerErrorCode errorCode, byte[] ciphertext, Object extra);
// }
// 
// Path: lib-android/src/main/java/com/google/capillary/android/CapillaryHandlerErrorCode.java
// public enum CapillaryHandlerErrorCode {
//   // A ciphertext that was encrypted using an authenticated Capillary public key was received in a
//   // device that does not have authentication enabled.
//   AUTH_CIPHER_IN_NO_AUTH_DEVICE,
//   // A malformed ciphertext was received.
//   MALFORMED_CIPHERTEXT,
//   // A ciphertext that was encrypted using an older Capillary public key was received. The client
//   // should re-register the current Capillary public key with the application server to avoid
//   // this error happening again.
//   STALE_CIPHERTEXT,
//   // An error other than the above has occurred.
//   UNKNOWN_ERROR
// }


import android.content.Context;
import android.util.Log;
import com.google.capillary.android.CapillaryHandler;
import com.google.capillary.android.CapillaryHandlerErrorCode;
import com.google.capillary.demo.common.AddOrUpdatePublicKeyRequest;
import com.google.capillary.demo.common.DemoServiceGrpc;
import com.google.capillary.demo.common.DemoServiceGrpc.DemoServiceBlockingStub;
import com.google.capillary.demo.common.KeyAlgorithm;
import com.google.capillary.demo.common.SecureNotification;
import com.google.capillary.demo.common.SendMessageRequest;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import io.grpc.ManagedChannel;
   * This Capillary public key was generated due to a failure in decrypting a Capillary ciphertext.
   * Therefore, this method first registers the new Capillary public key with the application
   * server, and then requests the Capillary ciphertext to be resend.
   */
  @Override
  public void handlePublicKey(
      boolean isAuthKey, byte[] publicKey, byte[] ciphertext, Object extra) {
    handlePublicKey(isAuthKey, publicKey, extra);
    KeyAlgorithm keyAlgorithm = (KeyAlgorithm) extra;
    SendMessageRequest request = SendMessageRequest.newBuilder()
        .setUserId(Utils.getUserId(context))
        .setKeyAlgorithm(keyAlgorithm)
        .setIsAuthKey(isAuthKey)
        .setData(Utils.createSecureMessageBytes("retry msg", keyAlgorithm, isAuthKey)).build();
    blockingStub.sendMessage(request);
  }

  /**
   * This indicates that a Capillary ciphertext was saved to be decrypted later.
   */
  @Override
  public void authCiphertextSavedForLater(byte[] ciphertext, Object extra) {
    KeyAlgorithm keyAlgorithm = (KeyAlgorithm) extra;
    Log.d(TAG, String.format("ciphertext saved: KeyAlgorithm=%s", keyAlgorithm));
  }

  /**
   * This indicates an error.
   */
  @Override
// Path: lib-android/src/main/java/com/google/capillary/android/CapillaryHandler.java
// public interface CapillaryHandler {
// 
//   /**
//    * Provides the plaintext after decrypting a Capillary ciphertext.
//    *
//    * @param isAuthKey whether the decryption was done using a public key requiring authentication.
//    * @param data the plaintext.
//    * @param extra the extra parameter originally passed to {@link DecrypterManager}.
//    */
//   void handleData(boolean isAuthKey, byte[] data, Object extra);
// 
//   /**
//    * Provides the generated Capillary public key.
//    *
//    * @param isAuthKey whether the public key requires authentication.
//    * @param publicKey the public key.
//    * @param extra the extra parameter originally passed to {@link KeyManager}.
//    */
//   void handlePublicKey(boolean isAuthKey, byte[] publicKey, Object extra);
// 
//   /**
//    * Provides the Capillary public key that was generated as a result of a decryption error.
//    *
//    * @param isAuthKey whether the public key requires authentication.
//    * @param publicKey the public key.
//    * @param ciphertext the ciphertext that caused the decryption error.
//    * @param extra the extra parameter originally passed to {@link DecrypterManager}.
//    */
//   void handlePublicKey(boolean isAuthKey, byte[] publicKey, byte[] ciphertext, Object extra);
// 
//   /**
//    * Signals that a Capillary ciphertext was saved to be decrypted after user authentication.
//    *
//    * @param ciphertext the saved Capillary ciphertext.
//    * @param extra the extra parameter originally passed to {@link DecrypterManager}.
//    */
//   void authCiphertextSavedForLater(byte[] ciphertext, Object extra);
// 
//   /**
//    * Signals that an error has occurred.
//    *
//    * @param errorCode the error code enum.
//    * @param ciphertext the Capillary ciphertext that is affected by this error.
//    * @param extra the extra parameter originally passed to {@link DecrypterManager}.
//    */
//   void error(CapillaryHandlerErrorCode errorCode, byte[] ciphertext, Object extra);
// }
// 
// Path: lib-android/src/main/java/com/google/capillary/android/CapillaryHandlerErrorCode.java
// public enum CapillaryHandlerErrorCode {
//   // A ciphertext that was encrypted using an authenticated Capillary public key was received in a
//   // device that does not have authentication enabled.
//   AUTH_CIPHER_IN_NO_AUTH_DEVICE,
//   // A malformed ciphertext was received.
//   MALFORMED_CIPHERTEXT,
//   // A ciphertext that was encrypted using an older Capillary public key was received. The client
//   // should re-register the current Capillary public key with the application server to avoid
//   // this error happening again.
//   STALE_CIPHERTEXT,
//   // An error other than the above has occurred.
//   UNKNOWN_ERROR
// }


// Path: demo/android/src/main/java/com/google/capillary/demo/android/DemoCapillaryHandler.java
import android.content.Context;
import android.util.Log;
import com.google.capillary.android.CapillaryHandler;
import com.google.capillary.android.CapillaryHandlerErrorCode;
import com.google.capillary.demo.common.AddOrUpdatePublicKeyRequest;
import com.google.capillary.demo.common.DemoServiceGrpc;
import com.google.capillary.demo.common.DemoServiceGrpc.DemoServiceBlockingStub;
import com.google.capillary.demo.common.KeyAlgorithm;
import com.google.capillary.demo.common.SecureNotification;
import com.google.capillary.demo.common.SendMessageRequest;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import io.grpc.ManagedChannel;

   * This Capillary public key was generated due to a failure in decrypting a Capillary ciphertext.
   * Therefore, this method first registers the new Capillary public key with the application
   * server, and then requests the Capillary ciphertext to be resend.
   */
  @Override
  public void handlePublicKey(
      boolean isAuthKey, byte[] publicKey, byte[] ciphertext, Object extra) {
    handlePublicKey(isAuthKey, publicKey, extra);
    KeyAlgorithm keyAlgorithm = (KeyAlgorithm) extra;
    SendMessageRequest request = SendMessageRequest.newBuilder()
        .setUserId(Utils.getUserId(context))
        .setKeyAlgorithm(keyAlgorithm)
        .setIsAuthKey(isAuthKey)
        .setData(Utils.createSecureMessageBytes("retry msg", keyAlgorithm, isAuthKey)).build();
    blockingStub.sendMessage(request);
  }

  /**
   * This indicates that a Capillary ciphertext was saved to be decrypted later.
   */
  @Override
  public void authCiphertextSavedForLater(byte[] ciphertext, Object extra) {
    KeyAlgorithm keyAlgorithm = (KeyAlgorithm) extra;
    Log.d(TAG, String.format("ciphertext saved: KeyAlgorithm=%s", keyAlgorithm));
  }

  /**
   * This indicates an error.
   */
  @Override
  public void error(CapillaryHandlerErrorCode errorCode, byte[] ciphertext, Object extra) {