message: This should provide a slight performance boost over cloning the
  Mac every time it is used and doesn't have to deal with edge cases.
  FIG_LOSSY_EXPORT=Don't submit from Critique.  Use hg submit instead, or sync and re-upload when the diffbase is submitted.  See go/fig-lossy-export
diff: @@ -22,14 +22,28 @@ import java.security.GeneralSecurityException;
  import java.security.InvalidAlgorithmParameterException;
  import java.security.NoSuchAlgorithmException;
  import java.util.Arrays;
  +import javax.crypto.Mac;
  /** {@link Prf} implementation using JCE. */
  @Immutable
  public final class PrfHmacJce implements Prf {
  static final int MIN_KEY_SIZE_IN_BYTES = 16;
  - @SuppressWarnings("Immutable") // We do not mutate the underlying mac.
  - private final javax.crypto.Mac mac;
  + // We do not mutate the underlying mac and it is bound to the containing PrfHmacJce instance.
  + @SuppressWarnings({"Immutable", "ThreadLocalUsage"})
  + private final ThreadLocal<Mac> localMac =
  + new ThreadLocal<Mac>() {
  + @Override
  + protected Mac initialValue() {
  + try {
  + Mac mac = EngineFactory.MAC.getInstance(algorithm);
  + mac.init(key);
  + return mac;
  + } catch (GeneralSecurityException ex) {
  + throw new IllegalStateException(ex);
  + }
  + }
  + };
  private final String algorithm;
  @SuppressWarnings("Immutable") // We do not mutate the key.
  @@ -40,7 +54,6 @@ public final class PrfHmacJce implements Prf {
  public PrfHmacJce(String algorithm, java.security.Key key) throws GeneralSecurityException {
  this.algorithm = algorithm;
  this.key = key;
  - this.mac = EngineFactory.MAC.getInstance(algorithm);
  if (key.getEncoded().length < MIN_KEY_SIZE_IN_BYTES) {
  throw new InvalidAlgorithmParameterException(
  "key size too small, need at least " + MIN_KEY_SIZE_IN_BYTES + " bytes");
  @@ -59,7 +72,9 @@ public final class PrfHmacJce implements Prf {
  default:
  throw new NoSuchAlgorithmException("unknown Hmac algorithm: " + algorithm);
  }
  - mac.init(key);
  +
  + // Initialize the current threads mac, mostly to fail fast if anything is wrong.
  + localMac.get();
  }
  @Override
  @@ -68,17 +83,8 @@ public final class PrfHmacJce implements Prf {
  throw new InvalidAlgorithmParameterException("tag size too big");
  }
  - javax.crypto.Mac tmp;
  - try {
  - // Cloning a mac is frequently fast and thread-safe.
  - tmp = (javax.crypto.Mac) this.mac.clone();
  - } catch (java.lang.CloneNotSupportedException ex) {
  - // Unfortunately, the Mac interface in certain versions of Android is not clonable.
  - tmp = EngineFactory.MAC.getInstance(this.algorithm);
  - tmp.init(this.key);
  - }
  - tmp.update(data);
  - return Arrays.copyOf(tmp.doFinal(), outputLength);
  + localMac.get().update(data);
  + return Arrays.copyOf(localMac.get().doFinal(), outputLength);
  }
  /** Returns the maximum supported tag length. */
  