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.
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMultiset;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.errorprone.annotations.Immutable;
import com.google.errorprone.annotations.concurrent.LazyInit;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;
/**
 * Represents an <a href="http://en.wikipedia.org/wiki/Internet_media_type">Internet Media Type</a>
 * (also known as a MIME Type or Content Type). This class also supports the concept of media ranges
 * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1">defined by HTTP/1.1</a>.
 * As such, the {@code *} character is treated as a wildcard and is used to represent any acceptable
 * type or subtype value. A media type may not have wildcard type with a declared subtype. The
 * {@code *} character has no special meaning as part of a parameter. All values for type, subtype,
 * parameter attributes or parameter values must be valid according to RFCs <a
 * href="https://tools.ietf.org/html/rfc2045">2045</a> and <a
 * href="https://tools.ietf.org/html/rfc2046">2046</a>.
 *
 * <p>All portions of the media type that are case-insensitive (type, subtype, parameter attributes)
 * are normalized to lowercase. The value of the {@code charset} parameter is normalized to
 * lowercase, but all others are left as-is.
 *