This was almost certainly my fault, but as I look at the implementation of Sets.cartesianProduct, I think its `contains` method made the assumption that `ImmutableSet.asList().indexOf` was O(1), which is no longer the case for Android.  It should probably get a specific `contains` implementation that actually is O(sets), not O(sets*setSize).
*     ...
   *     ImmutableList<B> tuple = ImmutableList.of(b0, b1, ...);
   *     // operate on tuple
   *   }
   * }
   * }</pre>
   *
   * <p>Note that if any input set is empty, the Cartesian product will also be empty. If no sets at
   * all are provided (an empty list), the resulting Cartesian product has one element, an empty
   * list (counter-intuitive, but mathematically consistent).
   *
   * <p><i>Performance notes:</i> while the cartesian product of sets of size {@code m, n, p} is a
   * set of size {@code m x n x p}, its actual memory consumption is much smaller. When the
   * cartesian set is constructed, the input sets are merely copied. Only as the resulting set is
   * iterated are the individual lists created, and these are not retained after iteration.
   *
   * @param sets the sets to choose elements from, in the order that the elements chosen from those
   *     sets should appear in the resulting lists
   * @param <B> any common base class shared by all axes (often just {@link Object})
   * @return the Cartesian product, as an immutable set containing immutable lists
   * @throws NullPointerException if {@code sets}, any one of the {@code sets}, or any element of a
   *     provided set is null
   * @throws IllegalArgumentException if the cartesian product size exceeds the {@code int} range
   * @since 2.0
   */
  @SafeVarargs
  public static <B> Set<List<B>> cartesianProduct(Set<? extends B>... sets) {
    return cartesianProduct(Arrays.asList(sets));
  }
  private static final class CartesianSet<E> extends ForwardingCollection<List<E>>