// Path: lib/src/main/java/com/google/capillary/AuthModeUnavailableException.java
// public final class AuthModeUnavailableException extends CapillaryException {
// 
//   /**
//    * Creates a new {@link AuthModeUnavailableException} instance.
//    *
//    * @param msg the exception message.
//    */
//   public AuthModeUnavailableException(String msg) {
//     super(msg);
//   }
// }
// 
// Path: lib/src/main/java/com/google/capillary/NoSuchKeyException.java
// public final class NoSuchKeyException extends CapillaryException {
// 
//   /**
//    * Creates a new {@link NoSuchKeyException} object.
//    *
//    * @param msg the exception message.
//    */
//   public NoSuchKeyException(String msg) {
//     super(msg);
//   }
// }


import android.content.Context;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.UserNotAuthenticatedException;
import com.google.capillary.AuthModeUnavailableException;
import com.google.capillary.NoSuchKeyException;
import com.google.capillary.internal.CapillaryCiphertext;
import com.google.crypto.tink.HybridDecrypt;
import com.google.protobuf.InvalidProtocolBufferException;
import java.security.GeneralSecurityException;
import java.security.UnrecoverableKeyException;
import java.util.List;
    // Save the ciphertext for later if the decryption key is not ready.
    if (capillaryCiphertext.getIsAuthKey() && utils.isScreenLocked(context)) {
      ciphertextStorage.save(ciphertext);
      handler.authCiphertextSavedForLater(ciphertext, extra);
      return;
    }

    byte[] rawCiphertext = capillaryCiphertext.getCiphertext().toByteArray();
    byte[] data;

    // Attempt decryption.
    try {
      HybridDecrypt decrypter = keyManager.getDecrypter(
          capillaryCiphertext.getKeychainUniqueId(),
          capillaryCiphertext.getKeySerialNumber(),
          capillaryCiphertext.getIsAuthKey());
      data = decrypter.decrypt(rawCiphertext, null);
    } catch (AuthModeUnavailableException e) {
      handler.error(CapillaryHandlerErrorCode.AUTH_CIPHER_IN_NO_AUTH_DEVICE, ciphertext, extra);
      return;
    } catch (Exception e) { // Needs to catch Exception here to support multiple API levels.
      // In API levels 23 and above, this happens when the user has enabled authentication, but
      // hasn't yet authenticated in the lock screen (e.g., added a new unlock code, but hasn't
      // locked the device yet.).
      if (VERSION.SDK_INT >= VERSION_CODES.M && e instanceof UserNotAuthenticatedException) {
        ciphertextStorage.save(ciphertext);
        handler.authCiphertextSavedForLater(ciphertext, extra);
        return;
      }
      // All these exceptions refer to missing or corrupt decryption keys.
// Path: lib/src/main/java/com/google/capillary/AuthModeUnavailableException.java
// public final class AuthModeUnavailableException extends CapillaryException {
// 
//   /**
//    * Creates a new {@link AuthModeUnavailableException} instance.
//    *
//    * @param msg the exception message.
//    */
//   public AuthModeUnavailableException(String msg) {
//     super(msg);
//   }
// }
// 
// Path: lib/src/main/java/com/google/capillary/NoSuchKeyException.java
// public final class NoSuchKeyException extends CapillaryException {
// 
//   /**
//    * Creates a new {@link NoSuchKeyException} object.
//    *
//    * @param msg the exception message.
//    */
//   public NoSuchKeyException(String msg) {
//     super(msg);
//   }
// }


// Path: lib-android/src/main/java/com/google/capillary/android/DecrypterManager.java
import android.content.Context;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.UserNotAuthenticatedException;
import com.google.capillary.AuthModeUnavailableException;
import com.google.capillary.NoSuchKeyException;
import com.google.capillary.internal.CapillaryCiphertext;
import com.google.crypto.tink.HybridDecrypt;
import com.google.protobuf.InvalidProtocolBufferException;
import java.security.GeneralSecurityException;
import java.security.UnrecoverableKeyException;
import java.util.List;

    // Save the ciphertext for later if the decryption key is not ready.
    if (capillaryCiphertext.getIsAuthKey() && utils.isScreenLocked(context)) {
      ciphertextStorage.save(ciphertext);
      handler.authCiphertextSavedForLater(ciphertext, extra);
      return;
    }

    byte[] rawCiphertext = capillaryCiphertext.getCiphertext().toByteArray();
    byte[] data;

    // Attempt decryption.
    try {
      HybridDecrypt decrypter = keyManager.getDecrypter(
          capillaryCiphertext.getKeychainUniqueId(),
          capillaryCiphertext.getKeySerialNumber(),
          capillaryCiphertext.getIsAuthKey());
      data = decrypter.decrypt(rawCiphertext, null);
    } catch (AuthModeUnavailableException e) {
      handler.error(CapillaryHandlerErrorCode.AUTH_CIPHER_IN_NO_AUTH_DEVICE, ciphertext, extra);
      return;
    } catch (Exception e) { // Needs to catch Exception here to support multiple API levels.
      // In API levels 23 and above, this happens when the user has enabled authentication, but
      // hasn't yet authenticated in the lock screen (e.g., added a new unlock code, but hasn't
      // locked the device yet.).
      if (VERSION.SDK_INT >= VERSION_CODES.M && e instanceof UserNotAuthenticatedException) {
        ciphertextStorage.save(ciphertext);
        handler.authCiphertextSavedForLater(ciphertext, extra);
        return;
      }
      // All these exceptions refer to missing or corrupt decryption keys.
      if (e instanceof NoSuchKeyException // Thrown by Capillary library.