I've found cases where `MediaType::toString` generates erroneous results.

One case is when the `MediaType` instance has a parameter of an empty value. This can happen when calling `withParameter("foo", "")`, or parsing `text/plain; foo=""`. When the parameters are later joined, the value is erroneously matched as a token instead of being quoted (as tokens cannot be empty). This will lead the following to throw `IllegalArgumentException`: 
```java
MediaType type1 = MediaType.parse("text/plain; foo=\"\"");
MediaType type2 = MediaType.parse(type1.toString()); // Trying to parse 'text/plain; foo=' will fail
```
 I think [this line](https://github.com/google/guava/blob/5a8f19bd3556012ed9e65cd4268a85ddde95733f/guava/src/com/google/common/net/MediaType.java#L1091) should first check if the string is empty before matching against `TOKEN_MATCHER`, or maybe just return the literal `"\"\""` on that case to avoid the `StringBuilder` allocation.

Another case is when parameters are set explicitly using `withParameter[s](...)`, where parameter value[s] contain non-ASCII characters. For example this will also throw `IllegalArgumentException`:
```java
MediaType type1 = MediaType.create("text", "plain").withParameter("let_me_in!", "\"جوافة\"");
MediaType type2 = MediaType.parse(type1.toString()); // The tokenizer will fail to consume QUOTED_TEXT_MATCHER
```
I don't know whether this is the intended behaviour or not but `MediaType::toString` can be used in HTTP header values which shouldn't contain non-ASCII octets. IMHO `normalizeParameterValue(...)` should validate the value against the `ascii()` matcher.
checkNotNull(attribute);
    checkNotNull(values);
    String normalizedAttribute = normalizeToken(attribute);
    ImmutableListMultimap.Builder<String, String> builder = ImmutableListMultimap.builder();
    for (Entry<String, String> entry : parameters.entries()) {
      String key = entry.getKey();
      if (!normalizedAttribute.equals(key)) {
        builder.put(key, entry.getValue());
      }
    }
    for (String value : values) {
      builder.put(normalizedAttribute, normalizeParameterValue(normalizedAttribute, value));
    }
    MediaType mediaType = new MediaType(type, subtype, builder.build());
    
    if (!normalizedAttribute.equals(CHARSET_ATTRIBUTE)) {
      mediaType.parsedCharset = this.parsedCharset;
    }
    
    return MoreObjects.firstNonNull(KNOWN_TYPES.get(mediaType), mediaType);
  }
  /**
   * <em>Replaces</em> all parameters with the given attribute with a single parameter with the
   * given value. If multiple parameters with the same attributes are necessary use {@link
   * #withParameters(String, Iterable)}. Prefer {@link #withCharset} for setting the {@code charset}
   * parameter when using a {@link Charset} object.
   *
   * @throws IllegalArgumentException if either {@code attribute} or {@code value} is invalid
   */
  public MediaType withParameter(String attribute, String value) {