Switch to OkHttp as URL's preferred HTTP implementation.

Change-Id: Id724b75dd78b68ed00f5db4989c4070896996ec0
diff --git a/Android.mk b/Android.mk
index 18cf576..d21b765 100644
--- a/Android.mk
+++ b/Android.mk
@@ -61,6 +61,7 @@
         core-hostdex \
         bouncycastle-hostdex \
         apache-xml-hostdex \
+        okhttp-hostdex \
         apache-harmony-tests-hostdex \
         $(call intermediates-dir-for,JAVA_LIBRARIES,core-tests,,COMMON)/classes.jar
 endif
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 98de1f2..7cb0aa4 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -96,8 +96,8 @@
 LOCAL_SRC_FILES := $(call all-test-java-files-under,dalvik dom json luni support xml)
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit
-LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc mockwebserver nist-pkix-tests
+LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit okhttp
+LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc mockwebserver nist-pkix-tests okhttp-tests
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_MODULE := core-tests
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
@@ -151,7 +151,7 @@
     LOCAL_SRC_FILES := $(call all-test-java-files-under,dalvik dom json luni support xml)
     LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
     LOCAL_NO_STANDARD_LIBRARIES := true
-    LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-hostdex core-junit-hostdex
+    LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-hostdex core-junit-hostdex okhttp-hostdex
     LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host
     LOCAL_JAVACFLAGS := $(local_javac_flags)
     LOCAL_MODULE_TAGS := optional
diff --git a/luni/src/main/java/java/net/ExtendedResponseCache.java b/luni/src/main/java/java/net/ExtendedResponseCache.java
deleted file mode 100644
index a70e734..0000000
--- a/luni/src/main/java/java/net/ExtendedResponseCache.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.net;
-
-/**
- * A response cache that supports statistics tracking and updating stored
- * responses. Implementations of {@link ResponseCache} should implement this
- * interface to receive additional support from the HTTP engine.
- *
- * @hide
- */
-public interface ExtendedResponseCache {
-
-    /*
-     * This hidden interface is defined in a non-hidden package (java.net) so
-     * its @hide tag will be parsed by Doclava. This hides this interface from
-     * implementing classes' documentation.
-     */
-
-    /**
-     * Track an HTTP response being satisfied by {@code source}.
-     * @hide
-     */
-    void trackResponse(ResponseSource source);
-
-    /**
-     * Track an conditional GET that was satisfied by this cache.
-     * @hide
-     */
-    void trackConditionalCacheHit();
-
-    /**
-     * Updates stored HTTP headers using a hit on a conditional GET.
-     * @hide
-     */
-    void update(CacheResponse conditionalCacheHit, HttpURLConnection httpConnection);
-}
diff --git a/luni/src/main/java/java/net/HttpURLConnection.java b/luni/src/main/java/java/net/HttpURLConnection.java
index 2023887..573dde6 100644
--- a/luni/src/main/java/java/net/HttpURLConnection.java
+++ b/luni/src/main/java/java/net/HttpURLConnection.java
@@ -20,7 +20,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Arrays;
-import libcore.net.http.HttpEngine;
 
 /**
  * An {@link URLConnection} for HTTP (<a
@@ -257,19 +256,20 @@
  * request/response pair. Instances of this class are not thread safe.
  */
 public abstract class HttpURLConnection extends URLConnection {
+    private static final int DEFAULT_CHUNK_LENGTH = 1024;
 
     /**
      * The subset of HTTP methods that the user may select via {@link
      * #setRequestMethod(String)}.
      */
     private static final String[] PERMITTED_USER_METHODS = {
-            HttpEngine.OPTIONS,
-            HttpEngine.GET,
-            HttpEngine.HEAD,
-            HttpEngine.POST,
-            HttpEngine.PUT,
-            HttpEngine.DELETE,
-            HttpEngine.TRACE
+            "OPTIONS",
+            "GET",
+            "HEAD",
+            "POST",
+            "PUT",
+            "DELETE",
+            "TRACE"
             // Note: we don't allow users to specify "CONNECT"
     };
 
@@ -277,7 +277,7 @@
      * The HTTP request method of this {@code HttpURLConnection}. The default
      * value is {@code "GET"}.
      */
-    protected String method = HttpEngine.GET;
+    protected String method = "GET";
 
     /**
      * The status code of the response obtained from the HTTP request. The
@@ -787,7 +787,7 @@
             throw new IllegalStateException("Already in fixed-length mode");
         }
         if (chunkLength <= 0) {
-            this.chunkLength = HttpEngine.DEFAULT_CHUNK_LENGTH;
+            this.chunkLength = DEFAULT_CHUNK_LENGTH;
         } else {
             this.chunkLength = chunkLength;
         }
diff --git a/luni/src/main/java/java/net/ResponseSource.java b/luni/src/main/java/java/net/ResponseSource.java
deleted file mode 100644
index fb974e9..0000000
--- a/luni/src/main/java/java/net/ResponseSource.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.net;
-
-/**
- * Where the HTTP client should look for a response.
- *
- * @hide
- */
-public enum ResponseSource {
-
-    /**
-     * Return the response from the cache immediately.
-     */
-    CACHE,
-
-    /**
-     * Make a conditional request to the host, returning the cache response if
-     * the cache is valid and the network response otherwise.
-     */
-    CONDITIONAL_CACHE,
-
-    /**
-     * Return the response from the network.
-     */
-    NETWORK;
-
-    public boolean requiresConnection() {
-        return this == CONDITIONAL_CACHE || this == NETWORK;
-    }
-}
diff --git a/luni/src/main/java/java/net/URL.java b/luni/src/main/java/java/net/URL.java
index 9d44498..dd487bc 100644
--- a/luni/src/main/java/java/net/URL.java
+++ b/luni/src/main/java/java/net/URL.java
@@ -24,8 +24,6 @@
 import java.io.Serializable;
 import java.util.Hashtable;
 import java.util.jar.JarFile;
-import libcore.net.http.HttpHandler;
-import libcore.net.http.HttpsHandler;
 import libcore.net.url.FileHandler;
 import libcore.net.url.FtpHandler;
 import libcore.net.url.JarHandler;
@@ -427,9 +425,19 @@
         } else if (protocol.equals("ftp")) {
             streamHandler = new FtpHandler();
         } else if (protocol.equals("http")) {
-            streamHandler = new HttpHandler();
+            try {
+                String name = "com.android.okhttp.HttpHandler";
+                streamHandler = (URLStreamHandler) Class.forName(name).newInstance();
+            } catch (Exception e) {
+                throw new AssertionError(e);
+            }
         } else if (protocol.equals("https")) {
-            streamHandler = new HttpsHandler();
+            try {
+                String name = "com.android.okhttp.HttpsHandler";
+                streamHandler = (URLStreamHandler) Class.forName(name).newInstance();
+            } catch (Exception e) {
+                throw new AssertionError(e);
+            }
         } else if (protocol.equals("jar")) {
             streamHandler = new JarHandler();
         }
diff --git a/luni/src/main/java/libcore/net/http/AbstractHttpInputStream.java b/luni/src/main/java/libcore/net/http/AbstractHttpInputStream.java
deleted file mode 100644
index 70f76b7..0000000
--- a/luni/src/main/java/libcore/net/http/AbstractHttpInputStream.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.CacheRequest;
-import libcore.io.Streams;
-
-/**
- * An input stream for the body of an HTTP response.
- *
- * <p>Since a single socket's input stream may be used to read multiple HTTP
- * responses from the same server, subclasses shouldn't close the socket stream.
- *
- * <p>A side effect of reading an HTTP response is that the response cache
- * is populated. If the stream is closed early, that cache entry will be
- * invalidated.
- */
-abstract class AbstractHttpInputStream extends InputStream {
-    protected final InputStream in;
-    protected final HttpEngine httpEngine;
-    private final CacheRequest cacheRequest;
-    private final OutputStream cacheBody;
-    protected boolean closed;
-
-    AbstractHttpInputStream(InputStream in, HttpEngine httpEngine,
-            CacheRequest cacheRequest) throws IOException {
-        this.in = in;
-        this.httpEngine = httpEngine;
-
-        OutputStream cacheBody = cacheRequest != null ? cacheRequest.getBody() : null;
-
-        // some apps return a null body; for compatibility we treat that like a null cache request
-        if (cacheBody == null) {
-            cacheRequest = null;
-        }
-
-        this.cacheBody = cacheBody;
-        this.cacheRequest = cacheRequest;
-    }
-
-    /**
-     * read() is implemented using read(byte[], int, int) so subclasses only
-     * need to override the latter.
-     */
-    @Override public final int read() throws IOException {
-        return Streams.readSingleByte(this);
-    }
-
-    protected final void checkNotClosed() throws IOException {
-        if (closed) {
-            throw new IOException("stream closed");
-        }
-    }
-
-    protected final void cacheWrite(byte[] buffer, int offset, int count) throws IOException {
-        if (cacheBody != null) {
-            cacheBody.write(buffer, offset, count);
-        }
-    }
-
-    /**
-     * Closes the cache entry and makes the socket available for reuse. This
-     * should be invoked when the end of the body has been reached.
-     */
-    protected final void endOfInput(boolean reuseSocket) throws IOException {
-        if (cacheRequest != null) {
-            cacheBody.close();
-        }
-        httpEngine.release(reuseSocket);
-    }
-
-    /**
-     * Calls abort on the cache entry and disconnects the socket. This
-     * should be invoked when the connection is closed unexpectedly to
-     * invalidate the cache entry and to prevent the HTTP connection from
-     * being reused. HTTP messages are sent in serial so whenever a message
-     * cannot be read to completion, subsequent messages cannot be read
-     * either and the connection must be discarded.
-     *
-     * <p>An earlier implementation skipped the remaining bytes, but this
-     * requires that the entire transfer be completed. If the intention was
-     * to cancel the transfer, closing the connection is the only solution.
-     */
-    protected final void unexpectedEndOfInput() {
-        if (cacheRequest != null) {
-            cacheRequest.abort();
-        }
-        httpEngine.release(false);
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/AbstractHttpOutputStream.java b/luni/src/main/java/libcore/net/http/AbstractHttpOutputStream.java
deleted file mode 100644
index 1e1b47b..0000000
--- a/luni/src/main/java/libcore/net/http/AbstractHttpOutputStream.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * An output stream for the body of an HTTP request.
- *
- * <p>Since a single socket's output stream may be used to write multiple HTTP
- * requests to the same server, subclasses should not close the socket stream.
- */
-abstract class AbstractHttpOutputStream extends OutputStream {
-    protected boolean closed;
-
-    @Override public final void write(int data) throws IOException {
-        write(new byte[] { (byte) data });
-    }
-
-    protected final void checkNotClosed() throws IOException {
-        if (closed) {
-            throw new IOException("stream closed");
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/Challenge.java b/luni/src/main/java/libcore/net/http/Challenge.java
deleted file mode 100644
index 0326c17..0000000
--- a/luni/src/main/java/libcore/net/http/Challenge.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-/**
- * An RFC 2617 challenge.
- *
- * @hide
- */
-public final class Challenge {
-    final String scheme;
-    final String realm;
-
-    public Challenge(String scheme, String realm) {
-        this.scheme = scheme;
-        this.realm = realm;
-    }
-
-    @Override public boolean equals(Object o) {
-        return o instanceof Challenge
-                && ((Challenge) o).scheme.equals(scheme)
-                && ((Challenge) o).realm.equals(realm);
-    }
-
-    @Override public int hashCode() {
-        return scheme.hashCode() + 31 * realm.hashCode();
-    }
-
-    @Override public String toString() {
-        return "Challenge[" + scheme + " " + realm + "]";
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/ChunkedInputStream.java b/luni/src/main/java/libcore/net/http/ChunkedInputStream.java
deleted file mode 100644
index 91cff7a..0000000
--- a/luni/src/main/java/libcore/net/http/ChunkedInputStream.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.CacheRequest;
-import java.util.Arrays;
-import libcore.io.Streams;
-
-/**
- * An HTTP body with alternating chunk sizes and chunk bodies.
- */
-final class ChunkedInputStream extends AbstractHttpInputStream {
-    private static final int MIN_LAST_CHUNK_LENGTH = "\r\n0\r\n\r\n".length();
-    private static final int NO_CHUNK_YET = -1;
-    private int bytesRemainingInChunk = NO_CHUNK_YET;
-    private boolean hasMoreChunks = true;
-
-    ChunkedInputStream(InputStream is, CacheRequest cacheRequest,
-            HttpEngine httpEngine) throws IOException {
-        super(is, httpEngine, cacheRequest);
-    }
-
-    @Override public int read(byte[] buffer, int offset, int count) throws IOException {
-        Arrays.checkOffsetAndCount(buffer.length, offset, count);
-        checkNotClosed();
-
-        if (!hasMoreChunks) {
-            return -1;
-        }
-        if (bytesRemainingInChunk == 0 || bytesRemainingInChunk == NO_CHUNK_YET) {
-            readChunkSize();
-            if (!hasMoreChunks) {
-                return -1;
-            }
-        }
-        int read = in.read(buffer, offset, Math.min(count, bytesRemainingInChunk));
-        if (read == -1) {
-            unexpectedEndOfInput(); // the server didn't supply the promised chunk length
-            throw new IOException("unexpected end of stream");
-        }
-        bytesRemainingInChunk -= read;
-        cacheWrite(buffer, offset, read);
-
-        /*
-         * If we're at the end of a chunk and the next chunk size is readable,
-         * read it! Reading the last chunk causes the underlying connection to
-         * be recycled and we want to do that as early as possible. Otherwise
-         * self-delimiting streams like gzip will never be recycled.
-         * http://code.google.com/p/android/issues/detail?id=7059
-         */
-        if (bytesRemainingInChunk == 0 && in.available() >= MIN_LAST_CHUNK_LENGTH) {
-            readChunkSize();
-        }
-
-        return read;
-    }
-
-    private void readChunkSize() throws IOException {
-        // read the suffix of the previous chunk
-        if (bytesRemainingInChunk != NO_CHUNK_YET) {
-            Streams.readAsciiLine(in);
-        }
-        String chunkSizeString = Streams.readAsciiLine(in);
-        int index = chunkSizeString.indexOf(";");
-        if (index != -1) {
-            chunkSizeString = chunkSizeString.substring(0, index);
-        }
-        try {
-            bytesRemainingInChunk = Integer.parseInt(chunkSizeString.trim(), 16);
-        } catch (NumberFormatException e) {
-            throw new IOException("Expected a hex chunk size, but was " + chunkSizeString);
-        }
-        if (bytesRemainingInChunk == 0) {
-            hasMoreChunks = false;
-            httpEngine.readTrailers();
-            endOfInput(true);
-        }
-    }
-
-    @Override public int available() throws IOException {
-        checkNotClosed();
-        if (!hasMoreChunks || bytesRemainingInChunk == NO_CHUNK_YET) {
-            return 0;
-        }
-        return Math.min(in.available(), bytesRemainingInChunk);
-    }
-
-    @Override public void close() throws IOException {
-        if (closed) {
-            return;
-        }
-
-        closed = true;
-        if (hasMoreChunks) {
-            unexpectedEndOfInput();
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/ChunkedOutputStream.java b/luni/src/main/java/libcore/net/http/ChunkedOutputStream.java
deleted file mode 100644
index db65f7b..0000000
--- a/luni/src/main/java/libcore/net/http/ChunkedOutputStream.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-
-/**
- * An HTTP body with alternating chunk sizes and chunk bodies. Chunks are
- * buffered until {@code maxChunkLength} bytes are ready, at which point the
- * chunk is written and the buffer is cleared.
- */
-final class ChunkedOutputStream extends AbstractHttpOutputStream {
-    private static final byte[] CRLF = { '\r', '\n' };
-    private static final byte[] HEX_DIGITS = {
-        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
-    };
-    private static final byte[] FINAL_CHUNK = new byte[] { '0', '\r', '\n', '\r', '\n' };
-
-    /** Scratch space for up to 8 hex digits, and then a constant CRLF */
-    private final byte[] hex = { 0, 0, 0, 0, 0, 0, 0, 0, '\r', '\n' };
-
-    private final OutputStream socketOut;
-    private final int maxChunkLength;
-    private final ByteArrayOutputStream bufferedChunk;
-
-
-    public ChunkedOutputStream(OutputStream socketOut, int maxChunkLength) {
-        this.socketOut = socketOut;
-        this.maxChunkLength = Math.max(1, dataLength(maxChunkLength));
-        this.bufferedChunk = new ByteArrayOutputStream(maxChunkLength);
-    }
-
-    /**
-     * Returns the amount of data that can be transmitted in a chunk whose total
-     * length (data+headers) is {@code dataPlusHeaderLength}. This is presumably
-     * useful to match sizes with wire-protocol packets.
-     */
-    private int dataLength(int dataPlusHeaderLength) {
-        int headerLength = 4; // "\r\n" after the size plus another "\r\n" after the data
-        for (int i = dataPlusHeaderLength - headerLength; i > 0; i >>= 4) {
-            headerLength++;
-        }
-        return dataPlusHeaderLength - headerLength;
-    }
-
-    @Override public synchronized void write(byte[] buffer, int offset, int count)
-            throws IOException {
-        checkNotClosed();
-        Arrays.checkOffsetAndCount(buffer.length, offset, count);
-
-        while (count > 0) {
-            int numBytesWritten;
-
-            if (bufferedChunk.size() > 0 || count < maxChunkLength) {
-                // fill the buffered chunk and then maybe write that to the stream
-                numBytesWritten = Math.min(count, maxChunkLength - bufferedChunk.size());
-                // TODO: skip unnecessary copies from buffer->bufferedChunk?
-                bufferedChunk.write(buffer, offset, numBytesWritten);
-                if (bufferedChunk.size() == maxChunkLength) {
-                    writeBufferedChunkToSocket();
-                }
-
-            } else {
-                // write a single chunk of size maxChunkLength to the stream
-                numBytesWritten = maxChunkLength;
-                writeHex(numBytesWritten);
-                socketOut.write(buffer, offset, numBytesWritten);
-                socketOut.write(CRLF);
-            }
-
-            offset += numBytesWritten;
-            count -= numBytesWritten;
-        }
-    }
-
-    /**
-     * Equivalent to, but cheaper than writing Integer.toHexString().getBytes()
-     * followed by CRLF.
-     */
-    private void writeHex(int i) throws IOException {
-        int cursor = 8;
-        do {
-            hex[--cursor] = HEX_DIGITS[i & 0xf];
-        } while ((i >>>= 4) != 0);
-        socketOut.write(hex, cursor, hex.length - cursor);
-    }
-
-    @Override public synchronized void flush() throws IOException {
-        if (closed) {
-            return; // don't throw; this stream might have been closed on the caller's behalf
-        }
-        writeBufferedChunkToSocket();
-        socketOut.flush();
-    }
-
-    @Override public synchronized void close() throws IOException {
-        if (closed) {
-            return;
-        }
-        closed = true;
-        writeBufferedChunkToSocket();
-        socketOut.write(FINAL_CHUNK);
-    }
-
-    private void writeBufferedChunkToSocket() throws IOException {
-        int size = bufferedChunk.size();
-        if (size <= 0) {
-            return;
-        }
-
-        writeHex(size);
-        bufferedChunk.writeTo(socketOut);
-        bufferedChunk.reset();
-        socketOut.write(CRLF);
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/FixedLengthInputStream.java b/luni/src/main/java/libcore/net/http/FixedLengthInputStream.java
deleted file mode 100644
index 1091af7..0000000
--- a/luni/src/main/java/libcore/net/http/FixedLengthInputStream.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.CacheRequest;
-import java.util.Arrays;
-
-/**
- * An HTTP body with a fixed length specified in advance.
- */
-final class FixedLengthInputStream extends AbstractHttpInputStream {
-    private int bytesRemaining;
-
-    public FixedLengthInputStream(InputStream is, CacheRequest cacheRequest,
-            HttpEngine httpEngine, int length) throws IOException {
-        super(is, httpEngine, cacheRequest);
-        bytesRemaining = length;
-        if (bytesRemaining == 0) {
-            endOfInput(true);
-        }
-    }
-
-    @Override public int read(byte[] buffer, int offset, int count) throws IOException {
-        Arrays.checkOffsetAndCount(buffer.length, offset, count);
-        checkNotClosed();
-        if (bytesRemaining == 0) {
-            return -1;
-        }
-        int read = in.read(buffer, offset, Math.min(count, bytesRemaining));
-        if (read == -1) {
-            unexpectedEndOfInput(); // the server didn't supply the promised content length
-            throw new IOException("unexpected end of stream");
-        }
-        bytesRemaining -= read;
-        cacheWrite(buffer, offset, read);
-        if (bytesRemaining == 0) {
-            endOfInput(true);
-        }
-        return read;
-    }
-
-    @Override public int available() throws IOException {
-        checkNotClosed();
-        return bytesRemaining == 0 ? 0 : Math.min(in.available(), bytesRemaining);
-    }
-
-    @Override public void close() throws IOException {
-        if (closed) {
-            return;
-        }
-        closed = true;
-        if (bytesRemaining != 0) {
-            unexpectedEndOfInput();
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/FixedLengthOutputStream.java b/luni/src/main/java/libcore/net/http/FixedLengthOutputStream.java
deleted file mode 100644
index 461eed9..0000000
--- a/luni/src/main/java/libcore/net/http/FixedLengthOutputStream.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-
-/**
- * An HTTP body with a fixed length known in advance.
- */
-final class FixedLengthOutputStream extends AbstractHttpOutputStream {
-    private final OutputStream socketOut;
-    private int bytesRemaining;
-
-    public FixedLengthOutputStream(OutputStream socketOut, int bytesRemaining) {
-        this.socketOut = socketOut;
-        this.bytesRemaining = bytesRemaining;
-    }
-
-    @Override public void write(byte[] buffer, int offset, int count) throws IOException {
-        checkNotClosed();
-        Arrays.checkOffsetAndCount(buffer.length, offset, count);
-        if (count > bytesRemaining) {
-            throw new IOException("expected " + bytesRemaining + " bytes but received " + count);
-        }
-        socketOut.write(buffer, offset, count);
-        bytesRemaining -= count;
-    }
-
-    @Override public void flush() throws IOException {
-        if (closed) {
-            return; // don't throw; this stream might have been closed on the caller's behalf
-        }
-        socketOut.flush();
-    }
-
-    @Override public void close() throws IOException {
-        if (closed) {
-            return;
-        }
-        closed = true;
-        if (bytesRemaining > 0) {
-            throw new IOException("unexpected end of stream");
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HeaderParser.java b/luni/src/main/java/libcore/net/http/HeaderParser.java
deleted file mode 100644
index 8d5770e..0000000
--- a/luni/src/main/java/libcore/net/http/HeaderParser.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @hide
- */
-public final class HeaderParser {
-
-    public interface CacheControlHandler {
-        void handle(String directive, String parameter);
-    }
-
-    /**
-     * Parse a comma-separated list of cache control header values.
-     */
-    public static void parseCacheControl(String value, CacheControlHandler handler) {
-        int pos = 0;
-        while (pos < value.length()) {
-            int tokenStart = pos;
-            pos = skipUntil(value, pos, "=,");
-            String directive = value.substring(tokenStart, pos).trim();
-
-            if (pos == value.length() || value.charAt(pos) == ',') {
-                pos++; // consume ',' (if necessary)
-                handler.handle(directive, null);
-                continue;
-            }
-
-            pos++; // consume '='
-            pos = skipWhitespace(value, pos);
-
-            String parameter;
-
-            // quoted string
-            if (pos < value.length() && value.charAt(pos) == '\"') {
-                pos++; // consume '"' open quote
-                int parameterStart = pos;
-                pos = skipUntil(value, pos, "\"");
-                parameter = value.substring(parameterStart, pos);
-                pos++; // consume '"' close quote (if necessary)
-
-            // unquoted string
-            } else {
-                int parameterStart = pos;
-                pos = skipUntil(value, pos, ",");
-                parameter = value.substring(parameterStart, pos).trim();
-            }
-
-            handler.handle(directive, parameter);
-        }
-    }
-
-    /**
-     * Parse RFC 2617 challenges. This API is only interested in the scheme
-     * name and realm.
-     */
-    public static List<Challenge> parseChallenges(
-            RawHeaders responseHeaders, String challengeHeader) {
-        /*
-         * auth-scheme = token
-         * auth-param  = token "=" ( token | quoted-string )
-         * challenge   = auth-scheme 1*SP 1#auth-param
-         * realm       = "realm" "=" realm-value
-         * realm-value = quoted-string
-         */
-        List<Challenge> result = new ArrayList<Challenge>();
-        for (int h = 0; h < responseHeaders.length(); h++) {
-            if (!challengeHeader.equalsIgnoreCase(responseHeaders.getFieldName(h))) {
-                continue;
-            }
-            String value = responseHeaders.getValue(h);
-            int pos = 0;
-            while (pos < value.length()) {
-                int tokenStart = pos;
-                pos = skipUntil(value, pos, " ");
-
-                String scheme = value.substring(tokenStart, pos).trim();
-                pos = skipWhitespace(value, pos);
-
-                // TODO: This currently only handles schemes with a 'realm' parameter;
-                //       It needs to be fixed to handle any scheme and any parameters
-                //       http://code.google.com/p/android/issues/detail?id=11140
-
-                if (!value.regionMatches(pos, "realm=\"", 0, "realm=\"".length())) {
-                    break; // unexpected challenge parameter; give up
-                }
-
-                pos += "realm=\"".length();
-                int realmStart = pos;
-                pos = skipUntil(value, pos, "\"");
-                String realm = value.substring(realmStart, pos);
-                pos++; // consume '"' close quote
-                pos = skipUntil(value, pos, ",");
-                pos++; // consume ',' comma
-                pos = skipWhitespace(value, pos);
-                result.add(new Challenge(scheme, realm));
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Returns the next index in {@code input} at or after {@code pos} that
-     * contains a character from {@code characters}. Returns the input length if
-     * none of the requested characters can be found.
-     */
-    private static int skipUntil(String input, int pos, String characters) {
-        for (; pos < input.length(); pos++) {
-            if (characters.indexOf(input.charAt(pos)) != -1) {
-                break;
-            }
-        }
-        return pos;
-    }
-
-    /**
-     * Returns the next non-whitespace character in {@code input} that is white
-     * space. Result is undefined if input contains newline characters.
-     */
-    private static int skipWhitespace(String input, int pos) {
-        for (; pos < input.length(); pos++) {
-            char c = input.charAt(pos);
-            if (c != ' ' && c != '\t') {
-                break;
-            }
-        }
-        return pos;
-    }
-
-    /**
-     * Returns {@code value} as a positive integer, or 0 if it is negative, or
-     * -1 if it cannot be parsed.
-     */
-    public static int parseSeconds(String value) {
-        try {
-            long seconds = Long.parseLong(value);
-            if (seconds > Integer.MAX_VALUE) {
-                return Integer.MAX_VALUE;
-            } else if (seconds < 0) {
-                return 0;
-            } else {
-                return (int) seconds;
-            }
-        } catch (NumberFormatException e) {
-            return -1;
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpConnection.java b/luni/src/main/java/libcore/net/http/HttpConnection.java
deleted file mode 100644
index 4a6e65d..0000000
--- a/luni/src/main/java/libcore/net/http/HttpConnection.java
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-import java.net.ProxySelector;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.net.URI;
-import java.net.UnknownHostException;
-import java.util.List;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import libcore.io.IoUtils;
-import libcore.util.Objects;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
-
-/**
- * Holds the sockets and streams of an HTTP or HTTPS connection, which may be
- * used for multiple HTTP request/response exchanges. Connections may be direct
- * to the origin server or via a proxy. Create an instance using the {@link
- * Address} inner class.
- *
- * <p>Do not confuse this class with the misnamed {@code HttpURLConnection},
- * which isn't so much a connection as a single request/response pair.
- */
-final class HttpConnection {
-    private final Address address;
-    private final Socket socket;
-    private InputStream inputStream;
-    private OutputStream outputStream;
-    private SSLSocket unverifiedSocket;
-    private SSLSocket sslSocket;
-    private InputStream sslInputStream;
-    private OutputStream sslOutputStream;
-    private boolean recycled = false;
-
-    private HttpConnection(Address config, int connectTimeout) throws IOException {
-        this.address = config;
-
-        /*
-         * Try each of the host's addresses for best behavior in mixed IPv4/IPv6
-         * environments. See http://b/2876927
-         * TODO: add a hidden method so that Socket.tryAllAddresses can does this for us
-         */
-        Socket socketCandidate = null;
-        InetAddress[] addresses = InetAddress.getAllByName(config.socketHost);
-        for (int i = 0; i < addresses.length; i++) {
-            socketCandidate = (config.proxy != null && config.proxy.type() != Proxy.Type.HTTP)
-                    ? new Socket(config.proxy)
-                    : new Socket();
-            try {
-                socketCandidate.connect(
-                        new InetSocketAddress(addresses[i], config.socketPort), connectTimeout);
-                break;
-            } catch (IOException e) {
-                if (i == addresses.length - 1) {
-                    throw e;
-                }
-            }
-        }
-
-        this.socket = socketCandidate;
-    }
-
-    public static HttpConnection connect(URI uri, SSLSocketFactory sslSocketFactory,
-            Proxy proxy, boolean requiresTunnel, int connectTimeout) throws IOException {
-        /*
-         * Try an explicitly-specified proxy.
-         */
-        if (proxy != null) {
-            Address address = (proxy.type() == Proxy.Type.DIRECT)
-                    ? new Address(uri, sslSocketFactory)
-                    : new Address(uri, sslSocketFactory, proxy, requiresTunnel);
-            return HttpConnectionPool.INSTANCE.get(address, connectTimeout);
-        }
-
-        /*
-         * Try connecting to each of the proxies provided by the ProxySelector
-         * until a connection succeeds.
-         */
-        ProxySelector selector = ProxySelector.getDefault();
-        List<Proxy> proxyList = selector.select(uri);
-        if (proxyList != null) {
-            for (Proxy selectedProxy : proxyList) {
-                if (selectedProxy.type() == Proxy.Type.DIRECT) {
-                    // the same as NO_PROXY
-                    // TODO: if the selector recommends a direct connection, attempt that?
-                    continue;
-                }
-                try {
-                    Address address = new Address(uri, sslSocketFactory,
-                            selectedProxy, requiresTunnel);
-                    return HttpConnectionPool.INSTANCE.get(address, connectTimeout);
-                } catch (IOException e) {
-                    // failed to connect, tell it to the selector
-                    selector.connectFailed(uri, selectedProxy.address(), e);
-                }
-            }
-        }
-
-        /*
-         * Try a direct connection. If this fails, this method will throw.
-         */
-        return HttpConnectionPool.INSTANCE.get(new Address(uri, sslSocketFactory), connectTimeout);
-    }
-
-    public void closeSocketAndStreams() {
-        IoUtils.closeQuietly(sslOutputStream);
-        IoUtils.closeQuietly(sslInputStream);
-        IoUtils.closeQuietly(sslSocket);
-        IoUtils.closeQuietly(outputStream);
-        IoUtils.closeQuietly(inputStream);
-        IoUtils.closeQuietly(socket);
-    }
-
-    public void setSoTimeout(int readTimeout) throws SocketException {
-        socket.setSoTimeout(readTimeout);
-    }
-
-    public OutputStream getOutputStream() throws IOException {
-        if (sslSocket != null) {
-            if (sslOutputStream == null) {
-                sslOutputStream = sslSocket.getOutputStream();
-            }
-            return sslOutputStream;
-        } else if(outputStream == null) {
-            outputStream = socket.getOutputStream();
-        }
-        return outputStream;
-    }
-
-    public InputStream getInputStream() throws IOException {
-        if (sslSocket != null) {
-            if (sslInputStream == null) {
-                sslInputStream = sslSocket.getInputStream();
-            }
-            return sslInputStream;
-        } else if (inputStream == null) {
-            /*
-             * Buffer the socket stream to permit efficient parsing of HTTP
-             * headers and chunk sizes. Benchmarks suggest 128 is sufficient.
-             * We cannot buffer when setting up a tunnel because we may consume
-             * bytes intended for the SSL socket.
-             */
-            int bufferSize = 128;
-            inputStream = address.requiresTunnel
-                    ? socket.getInputStream()
-                    : new BufferedInputStream(socket.getInputStream(), bufferSize);
-        }
-        return inputStream;
-    }
-
-    protected Socket getSocket() {
-        return sslSocket != null ? sslSocket : socket;
-    }
-
-    public Address getAddress() {
-        return address;
-    }
-
-    /**
-     * Create an {@code SSLSocket} and perform the SSL handshake
-     * (performing certificate validation.
-     *
-     * @param sslSocketFactory Source of new {@code SSLSocket} instances.
-     * @param tlsTolerant If true, assume server can handle common
-     * TLS extensions and SSL deflate compression. If false, use
-     * an SSL3 only fallback mode without compression.
-     */
-    public void setupSecureSocket(SSLSocketFactory sslSocketFactory, boolean tlsTolerant)
-            throws IOException {
-        // create the wrapper over connected socket
-        unverifiedSocket = (SSLSocket) sslSocketFactory.createSocket(socket,
-                address.uriHost, address.uriPort, true /* autoClose */);
-        // tlsTolerant mimics Chrome's behavior
-        if (tlsTolerant && unverifiedSocket instanceof OpenSSLSocketImpl) {
-            OpenSSLSocketImpl openSslSocket = (OpenSSLSocketImpl) unverifiedSocket;
-            openSslSocket.setUseSessionTickets(true);
-            openSslSocket.setHostname(address.uriHost);
-            // use SSLSocketFactory default enabled protocols
-        } else {
-            unverifiedSocket.setEnabledProtocols(new String [] { "SSLv3" });
-        }
-        // force handshake, which can throw
-        unverifiedSocket.startHandshake();
-    }
-
-    /**
-     * Return an {@code SSLSocket} that is not only connected but has
-     * also passed hostname verification.
-     *
-     * @param hostnameVerifier Used to verify the hostname we
-     * connected to is an acceptable match for the peer certificate
-     * chain of the SSLSession.
-     */
-    public SSLSocket verifySecureSocketHostname(HostnameVerifier hostnameVerifier)
-            throws IOException {
-        if (!hostnameVerifier.verify(address.uriHost, unverifiedSocket.getSession())) {
-            throw new IOException("Hostname '" + address.uriHost + "' was not verified");
-        }
-        sslSocket = unverifiedSocket;
-        return sslSocket;
-    }
-
-    /**
-     * Return an {@code SSLSocket} if already connected, otherwise null.
-     */
-    public SSLSocket getSecureSocketIfConnected() {
-        return sslSocket;
-    }
-
-    /**
-     * Returns true if this connection has been used to satisfy an earlier
-     * HTTP request/response pair.
-     */
-    public boolean isRecycled() {
-        return recycled;
-    }
-
-    public void setRecycled() {
-        this.recycled = true;
-    }
-
-    /**
-     * Returns true if this connection is eligible to be reused for another
-     * request/response pair.
-     */
-    protected boolean isEligibleForRecycling() {
-        return !socket.isClosed()
-                && !socket.isInputShutdown()
-                && !socket.isOutputShutdown();
-    }
-
-    /**
-     * This address has two parts: the address we connect to directly and the
-     * origin address of the resource. These are the same unless a proxy is
-     * being used. It also includes the SSL socket factory so that a socket will
-     * not be reused if its SSL configuration is different.
-     */
-    public static final class Address {
-        private final Proxy proxy;
-        private final boolean requiresTunnel;
-        private final String uriHost;
-        private final int uriPort;
-        private final String socketHost;
-        private final int socketPort;
-        private final SSLSocketFactory sslSocketFactory;
-
-        public Address(URI uri, SSLSocketFactory sslSocketFactory) throws UnknownHostException {
-            this.proxy = null;
-            this.requiresTunnel = false;
-            this.uriHost = uri.getHost();
-            this.uriPort = uri.getEffectivePort();
-            this.sslSocketFactory = sslSocketFactory;
-            this.socketHost = uriHost;
-            this.socketPort = uriPort;
-            if (uriHost == null) {
-                throw new UnknownHostException(uri.toString());
-            }
-        }
-
-        /**
-         * @param requiresTunnel true if the HTTP connection needs to tunnel one
-         *     protocol over another, such as when using HTTPS through an HTTP
-         *     proxy. When doing so, we must avoid buffering bytes intended for
-         *     the higher-level protocol.
-         */
-        public Address(URI uri, SSLSocketFactory sslSocketFactory,
-                Proxy proxy, boolean requiresTunnel) throws UnknownHostException {
-            this.proxy = proxy;
-            this.requiresTunnel = requiresTunnel;
-            this.uriHost = uri.getHost();
-            this.uriPort = uri.getEffectivePort();
-            this.sslSocketFactory = sslSocketFactory;
-
-            SocketAddress proxyAddress = proxy.address();
-            if (!(proxyAddress instanceof InetSocketAddress)) {
-                throw new IllegalArgumentException("Proxy.address() is not an InetSocketAddress: "
-                        + proxyAddress.getClass());
-            }
-            InetSocketAddress proxySocketAddress = (InetSocketAddress) proxyAddress;
-            this.socketHost = proxySocketAddress.getHostName();
-            this.socketPort = proxySocketAddress.getPort();
-            if (uriHost == null) {
-                throw new UnknownHostException(uri.toString());
-            }
-        }
-
-        public Proxy getProxy() {
-            return proxy;
-        }
-
-        @Override public boolean equals(Object other) {
-            if (other instanceof Address) {
-                Address that = (Address) other;
-                return Objects.equal(this.proxy, that.proxy)
-                        && this.uriHost.equals(that.uriHost)
-                        && this.uriPort == that.uriPort
-                        && Objects.equal(this.sslSocketFactory, that.sslSocketFactory)
-                        && this.requiresTunnel == that.requiresTunnel;
-            }
-            return false;
-        }
-
-        @Override public int hashCode() {
-            int result = 17;
-            result = 31 * result + uriHost.hashCode();
-            result = 31 * result + uriPort;
-            result = 31 * result + (sslSocketFactory != null ? sslSocketFactory.hashCode() : 0);
-            result = 31 * result + (proxy != null ? proxy.hashCode() : 0);
-            result = 31 * result + (requiresTunnel ? 1 : 0);
-            return result;
-        }
-
-        public HttpConnection connect(int connectTimeout) throws IOException {
-            return new HttpConnection(this, connectTimeout);
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpConnectionPool.java b/luni/src/main/java/libcore/net/http/HttpConnectionPool.java
deleted file mode 100644
index 1f5f4d9..0000000
--- a/luni/src/main/java/libcore/net/http/HttpConnectionPool.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package libcore.net.http;
-
-import dalvik.system.SocketTagger;
-import java.io.IOException;
-import java.net.Socket;
-import java.net.SocketException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * A pool of HTTP connections. This class exposes its tuning parameters as
- * system properties:
- * <ul>
- *   <li>{@code http.keepAlive} true if HTTP connections should be pooled at
- *       all. Default is true.
- *   <li>{@code http.maxConnections} maximum number of connections to each URI.
- *       Default is 5.
- * </ul>
- *
- * <p>This class <i>doesn't</i> adjust its configuration as system properties
- * are changed. This assumes that the applications that set these parameters do
- * so before making HTTP connections, and that this class is initialized lazily.
- */
-final class HttpConnectionPool {
-
-    public static final HttpConnectionPool INSTANCE = new HttpConnectionPool();
-
-    private final int maxConnections;
-    private final HashMap<HttpConnection.Address, List<HttpConnection>> connectionPool
-            = new HashMap<HttpConnection.Address, List<HttpConnection>>();
-
-    private HttpConnectionPool() {
-        String keepAlive = System.getProperty("http.keepAlive");
-        if (keepAlive != null && !Boolean.parseBoolean(keepAlive)) {
-            maxConnections = 0;
-            return;
-        }
-
-        String maxConnectionsString = System.getProperty("http.maxConnections");
-        this.maxConnections = maxConnectionsString != null
-                ? Integer.parseInt(maxConnectionsString)
-                : 5;
-    }
-
-    public HttpConnection get(HttpConnection.Address address, int connectTimeout)
-            throws IOException {
-        // First try to reuse an existing HTTP connection.
-        synchronized (connectionPool) {
-            List<HttpConnection> connections = connectionPool.get(address);
-            while (connections != null) {
-                HttpConnection connection = connections.remove(connections.size() - 1);
-                if (connections.isEmpty()) {
-                    connectionPool.remove(address);
-                    connections = null;
-                }
-                if (connection.isEligibleForRecycling()) {
-                    // Since Socket is recycled, re-tag before using
-                    Socket socket = connection.getSocket();
-                    SocketTagger.get().tag(socket);
-                    return connection;
-                }
-            }
-        }
-
-        /*
-         * We couldn't find a reusable connection, so we need to create a new
-         * connection. We're careful not to do so while holding a lock!
-         */
-        return address.connect(connectTimeout);
-    }
-
-    public void recycle(HttpConnection connection) {
-        Socket socket = connection.getSocket();
-        try {
-            SocketTagger.get().untag(socket);
-        } catch (SocketException e) {
-            // When unable to remove tagging, skip recycling and close
-            System.logW("Unable to untagSocket(): " + e);
-            connection.closeSocketAndStreams();
-            return;
-        }
-
-        if (maxConnections > 0 && connection.isEligibleForRecycling()) {
-            HttpConnection.Address address = connection.getAddress();
-            synchronized (connectionPool) {
-                List<HttpConnection> connections = connectionPool.get(address);
-                if (connections == null) {
-                    connections = new ArrayList<HttpConnection>();
-                    connectionPool.put(address, connections);
-                }
-                if (connections.size() < maxConnections) {
-                    connection.setRecycled();
-                    connections.add(connection);
-                    return; // keep the connection open
-                }
-            }
-        }
-
-        // don't close streams while holding a lock!
-        connection.closeSocketAndStreams();
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpEngine.java b/luni/src/main/java/libcore/net/http/HttpEngine.java
deleted file mode 100644
index 8d81c38..0000000
--- a/luni/src/main/java/libcore/net/http/HttpEngine.java
+++ /dev/null
@@ -1,852 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.CacheRequest;
-import java.net.CacheResponse;
-import java.net.CookieHandler;
-import java.net.ExtendedResponseCache;
-import java.net.HttpURLConnection;
-import java.net.Proxy;
-import java.net.ResponseCache;
-import java.net.ResponseSource;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.charset.Charsets;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.zip.GZIPInputStream;
-import javax.net.ssl.SSLSocketFactory;
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-import libcore.util.EmptyArray;
-
-/**
- * Handles a single HTTP request/response pair. Each HTTP engine follows this
- * lifecycle:
- * <ol>
- *     <li>It is created.
- *     <li>The HTTP request message is sent with sendRequest(). Once the request
- *         is sent it is an error to modify the request headers. After
- *         sendRequest() has been called the request body can be written to if
- *         it exists.
- *     <li>The HTTP response message is read with readResponse(). After the
- *         response has been read the response headers and body can be read.
- *         All responses have a response body input stream, though in some
- *         instances this stream is empty.
- * </ol>
- *
- * <p>The request and response may be served by the HTTP response cache, by the
- * network, or by both in the event of a conditional GET.
- *
- * <p>This class may hold a socket connection that needs to be released or
- * recycled. By default, this socket connection is held when the last byte of
- * the response is consumed. To release the connection when it is no longer
- * required, use {@link #automaticallyReleaseConnectionToPool()}.
- */
-public class HttpEngine {
-    private static final CacheResponse GATEWAY_TIMEOUT_RESPONSE = new CacheResponse() {
-        @Override public Map<String, List<String>> getHeaders() throws IOException {
-            Map<String, List<String>> result = new HashMap<String, List<String>>();
-            result.put(null, Collections.singletonList("HTTP/1.1 504 Gateway Timeout"));
-            return result;
-        }
-        @Override public InputStream getBody() throws IOException {
-            return new ByteArrayInputStream(EmptyArray.BYTE);
-        }
-    };
-
-    /**
-     * The maximum number of bytes to buffer when sending headers and a request
-     * body. When the headers and body can be sent in a single write, the
-     * request completes sooner. In one WiFi benchmark, using a large enough
-     * buffer sped up some uploads by half.
-     */
-    private static final int MAX_REQUEST_BUFFER_LENGTH = 32768;
-
-    public static final int DEFAULT_CHUNK_LENGTH = 1024;
-
-    public static final String OPTIONS = "OPTIONS";
-    public static final String GET = "GET";
-    public static final String HEAD = "HEAD";
-    public static final String POST = "POST";
-    public static final String PUT = "PUT";
-    public static final String DELETE = "DELETE";
-    public static final String TRACE = "TRACE";
-    public static final String CONNECT = "CONNECT";
-
-    public static final int HTTP_CONTINUE = 100;
-
-    /**
-     * HTTP 1.1 doesn't specify how many redirects to follow, but HTTP/1.0
-     * recommended 5. http://www.w3.org/Protocols/HTTP/1.0/spec.html#Code3xx
-     */
-    public static final int MAX_REDIRECTS = 5;
-
-    protected final HttpURLConnectionImpl policy;
-
-    protected final String method;
-
-    private ResponseSource responseSource;
-
-    protected HttpConnection connection;
-    private InputStream socketIn;
-    private OutputStream socketOut;
-
-    /**
-     * This stream buffers the request headers and the request body when their
-     * combined size is less than MAX_REQUEST_BUFFER_LENGTH. By combining them
-     * we can save socket writes, which in turn saves a packet transmission.
-     * This is socketOut if the request size is large or unknown.
-     */
-    private OutputStream requestOut;
-    private AbstractHttpOutputStream requestBodyOut;
-
-    private InputStream responseBodyIn;
-
-    private final ResponseCache responseCache = ResponseCache.getDefault();
-    private CacheResponse cacheResponse;
-    private CacheRequest cacheRequest;
-
-    /** The time when the request headers were written, or -1 if they haven't been written yet. */
-    private long sentRequestMillis = -1;
-
-    /**
-     * True if this client added an "Accept-Encoding: gzip" header field and is
-     * therefore responsible for also decompressing the transfer stream.
-     */
-    private boolean transparentGzip;
-
-    boolean sendChunked;
-
-    /**
-     * The version this client will use. Either 0 for HTTP/1.0, or 1 for
-     * HTTP/1.1. Upon receiving a non-HTTP/1.1 response, this client
-     * automatically sets its version to HTTP/1.0.
-     */
-    // TODO: is HTTP minor version tracked across HttpEngines?
-    private int httpMinorVersion = 1; // Assume HTTP/1.1
-
-    private final URI uri;
-
-    private final RequestHeaders requestHeaders;
-
-    /** Null until a response is received from the network or the cache */
-    private ResponseHeaders responseHeaders;
-
-    /*
-     * The cache response currently being validated on a conditional get. Null
-     * if the cached response doesn't exist or doesn't need validation. If the
-     * conditional get succeeds, these will be used for the response headers and
-     * body. If it fails, these be closed and set to null.
-     */
-    private ResponseHeaders cachedResponseHeaders;
-    private InputStream cachedResponseBody;
-
-    /**
-     * True if the socket connection should be released to the connection pool
-     * when the response has been fully read.
-     */
-    private boolean automaticallyReleaseConnectionToPool;
-
-    /** True if the socket connection is no longer needed by this engine. */
-    private boolean connectionReleased;
-
-    /**
-     * @param requestHeaders the client's supplied request headers. This class
-     *     creates a private copy that it can mutate.
-     * @param connection the connection used for an intermediate response
-     *     immediately prior to this request/response pair, such as a same-host
-     *     redirect. This engine assumes ownership of the connection and must
-     *     release it when it is unneeded.
-     */
-    public HttpEngine(HttpURLConnectionImpl policy, String method, RawHeaders requestHeaders,
-            HttpConnection connection, RetryableOutputStream requestBodyOut) throws IOException {
-        this.policy = policy;
-        this.method = method;
-        this.connection = connection;
-        this.requestBodyOut = requestBodyOut;
-
-        try {
-            uri = policy.getURL().toURILenient();
-        } catch (URISyntaxException e) {
-            throw new IOException(e);
-        }
-
-        this.requestHeaders = new RequestHeaders(uri, new RawHeaders(requestHeaders));
-    }
-
-    public URI getUri() {
-        return uri;
-    }
-
-    /**
-     * Figures out what the response source will be, and opens a socket to that
-     * source if necessary. Prepares the request headers and gets ready to start
-     * writing the request body if it exists.
-     */
-    public final void sendRequest() throws IOException {
-        if (responseSource != null) {
-            return;
-        }
-
-        prepareRawRequestHeaders();
-        initResponseSource();
-        if (responseCache instanceof ExtendedResponseCache) {
-            ((ExtendedResponseCache) responseCache).trackResponse(responseSource);
-        }
-
-        /*
-         * The raw response source may require the network, but the request
-         * headers may forbid network use. In that case, dispose of the network
-         * response and use a GATEWAY_TIMEOUT response instead, as specified
-         * by http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4.
-         */
-        if (requestHeaders.isOnlyIfCached() && responseSource.requiresConnection()) {
-            if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
-                IoUtils.closeQuietly(cachedResponseBody);
-            }
-            this.responseSource = ResponseSource.CACHE;
-            this.cacheResponse = GATEWAY_TIMEOUT_RESPONSE;
-            RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(cacheResponse.getHeaders());
-            setResponse(new ResponseHeaders(uri, rawResponseHeaders), cacheResponse.getBody());
-        }
-
-        if (responseSource.requiresConnection()) {
-            sendSocketRequest();
-        } else if (connection != null) {
-            HttpConnectionPool.INSTANCE.recycle(connection);
-            connection = null;
-        }
-    }
-
-    /**
-     * Initialize the source for this response. It may be corrected later if the
-     * request headers forbids network use.
-     */
-    private void initResponseSource() throws IOException {
-        responseSource = ResponseSource.NETWORK;
-        if (!policy.getUseCaches() || responseCache == null) {
-            return;
-        }
-
-        CacheResponse candidate = responseCache.get(uri, method,
-                requestHeaders.getHeaders().toMultimap());
-        if (candidate == null) {
-            return;
-        }
-
-        Map<String, List<String>> responseHeadersMap = candidate.getHeaders();
-        cachedResponseBody = candidate.getBody();
-        if (!acceptCacheResponseType(candidate)
-                || responseHeadersMap == null
-                || cachedResponseBody == null) {
-            IoUtils.closeQuietly(cachedResponseBody);
-            return;
-        }
-
-        RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(responseHeadersMap);
-        cachedResponseHeaders = new ResponseHeaders(uri, rawResponseHeaders);
-        long now = System.currentTimeMillis();
-        this.responseSource = cachedResponseHeaders.chooseResponseSource(now, requestHeaders);
-        if (responseSource == ResponseSource.CACHE) {
-            this.cacheResponse = candidate;
-            setResponse(cachedResponseHeaders, cachedResponseBody);
-        } else if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
-            this.cacheResponse = candidate;
-        } else if (responseSource == ResponseSource.NETWORK) {
-            IoUtils.closeQuietly(cachedResponseBody);
-        } else {
-            throw new AssertionError();
-        }
-    }
-
-    private void sendSocketRequest() throws IOException {
-        if (connection == null) {
-            connect();
-        }
-
-        if (socketOut != null || requestOut != null || socketIn != null) {
-            throw new IllegalStateException();
-        }
-
-        socketOut = connection.getOutputStream();
-        requestOut = socketOut;
-        socketIn = connection.getInputStream();
-
-        if (hasRequestBody()) {
-            initRequestBodyOut();
-        }
-    }
-
-    /**
-     * Connect to the origin server either directly or via a proxy.
-     */
-    protected void connect() throws IOException {
-        if (connection == null) {
-            connection = openSocketConnection();
-        }
-    }
-
-    protected final HttpConnection openSocketConnection() throws IOException {
-        HttpConnection result = HttpConnection.connect(uri, getSslSocketFactory(),
-                policy.getProxy(), requiresTunnel(), policy.getConnectTimeout());
-        Proxy proxy = result.getAddress().getProxy();
-        if (proxy != null) {
-            policy.setProxy(proxy);
-        }
-        result.setSoTimeout(policy.getReadTimeout());
-        return result;
-    }
-
-    protected void initRequestBodyOut() throws IOException {
-        int chunkLength = policy.getChunkLength();
-        if (chunkLength > 0 || requestHeaders.isChunked()) {
-            sendChunked = true;
-            if (chunkLength == -1) {
-                chunkLength = DEFAULT_CHUNK_LENGTH;
-            }
-        }
-
-        if (socketOut == null) {
-            throw new IllegalStateException("No socket to write to; was a POST cached?");
-        }
-
-        if (httpMinorVersion == 0) {
-            sendChunked = false;
-        }
-
-        int fixedContentLength = policy.getFixedContentLength();
-        if (requestBodyOut != null) {
-            // request body was already initialized by the predecessor HTTP engine
-        } else if (fixedContentLength != -1) {
-            writeRequestHeaders(fixedContentLength);
-            requestBodyOut = new FixedLengthOutputStream(requestOut, fixedContentLength);
-        } else if (sendChunked) {
-            writeRequestHeaders(-1);
-            requestBodyOut = new ChunkedOutputStream(requestOut, chunkLength);
-        } else if (requestHeaders.getContentLength() != -1) {
-            writeRequestHeaders(requestHeaders.getContentLength());
-            requestBodyOut = new RetryableOutputStream(requestHeaders.getContentLength());
-        } else {
-            requestBodyOut = new RetryableOutputStream();
-        }
-    }
-
-    /**
-     * @param body the response body, or null if it doesn't exist or isn't
-     *     available.
-     */
-    private void setResponse(ResponseHeaders headers, InputStream body) throws IOException {
-        if (this.responseBodyIn != null) {
-            throw new IllegalStateException();
-        }
-        this.responseHeaders = headers;
-        this.httpMinorVersion = responseHeaders.getHeaders().getHttpMinorVersion();
-        if (body != null) {
-            initContentStream(body);
-        }
-    }
-
-    private boolean hasRequestBody() {
-        return method == POST || method == PUT;
-    }
-
-    /**
-     * Returns the request body or null if this request doesn't have a body.
-     */
-    public final OutputStream getRequestBody() {
-        if (responseSource == null) {
-            throw new IllegalStateException();
-        }
-        return requestBodyOut;
-    }
-
-    public final boolean hasResponse() {
-        return responseHeaders != null;
-    }
-
-    public final RequestHeaders getRequestHeaders() {
-        return requestHeaders;
-    }
-
-    public final ResponseHeaders getResponseHeaders() {
-        if (responseHeaders == null) {
-            throw new IllegalStateException();
-        }
-        return responseHeaders;
-    }
-
-    public final int getResponseCode() {
-        if (responseHeaders == null) {
-            throw new IllegalStateException();
-        }
-        return responseHeaders.getHeaders().getResponseCode();
-    }
-
-    public final InputStream getResponseBody() {
-        if (responseHeaders == null) {
-            throw new IllegalStateException();
-        }
-        return responseBodyIn;
-    }
-
-    public final CacheResponse getCacheResponse() {
-        return cacheResponse;
-    }
-
-    public final HttpConnection getConnection() {
-        return connection;
-    }
-
-    public final boolean hasRecycledConnection() {
-        return connection != null && connection.isRecycled();
-    }
-
-    /**
-     * Returns true if {@code cacheResponse} is of the right type. This
-     * condition is necessary but not sufficient for the cached response to
-     * be used.
-     */
-    protected boolean acceptCacheResponseType(CacheResponse cacheResponse) {
-        return true;
-    }
-
-    private void maybeCache() throws IOException {
-        // Never cache responses to proxy CONNECT requests.
-        if (method == CONNECT) {
-            return;
-        }
-
-        // Are we caching at all?
-        if (!policy.getUseCaches() || responseCache == null) {
-            return;
-        }
-
-        // Should we cache this response for this request?
-        if (!responseHeaders.isCacheable(requestHeaders)) {
-            return;
-        }
-
-        // Offer this request to the cache.
-        cacheRequest = responseCache.put(uri, getHttpConnectionToCache());
-    }
-
-    protected HttpURLConnection getHttpConnectionToCache() {
-        return policy;
-    }
-
-    /**
-     * Cause the socket connection to be released to the connection pool when
-     * it is no longer needed. If it is already unneeded, it will be pooled
-     * immediately.
-     */
-    public final void automaticallyReleaseConnectionToPool() {
-        automaticallyReleaseConnectionToPool = true;
-        if (connection != null && connectionReleased) {
-            HttpConnectionPool.INSTANCE.recycle(connection);
-            connection = null;
-        }
-    }
-
-    public final void markConnectionAsRecycled() {
-        if (connection != null) {
-            connection.setRecycled();
-        }
-    }
-
-    /**
-     * Releases this engine so that its resources may be either reused or
-     * closed.
-     */
-    public final void release(boolean reusable) {
-        // If the response body comes from the cache, close it.
-        if (responseBodyIn == cachedResponseBody) {
-            IoUtils.closeQuietly(responseBodyIn);
-        }
-
-        if (!connectionReleased && connection != null) {
-            connectionReleased = true;
-
-            // We cannot reuse sockets that have incomplete output.
-            if (requestBodyOut != null && !requestBodyOut.closed) {
-                reusable = false;
-            }
-
-            // If the request specified that the connection shouldn't be reused,
-            // don't reuse it. This advice doesn't apply to CONNECT requests because
-            // the "Connection: close" header goes the origin server, not the proxy.
-            if (requestHeaders.hasConnectionClose() && method != CONNECT) {
-                reusable = false;
-            }
-
-            // If the response specified that the connection shouldn't be reused, don't reuse it.
-            if (responseHeaders != null && responseHeaders.hasConnectionClose()) {
-                reusable = false;
-            }
-
-            if (responseBodyIn instanceof UnknownLengthHttpInputStream) {
-                reusable = false;
-            }
-
-            if (reusable && responseBodyIn != null) {
-                // We must discard the response body before the connection can be reused.
-                try {
-                    Streams.skipAll(responseBodyIn);
-                } catch (IOException e) {
-                    reusable = false;
-                }
-            }
-
-            if (!reusable) {
-                connection.closeSocketAndStreams();
-                connection = null;
-            } else if (automaticallyReleaseConnectionToPool) {
-                HttpConnectionPool.INSTANCE.recycle(connection);
-                connection = null;
-            }
-        }
-    }
-
-    private void initContentStream(InputStream transferStream) throws IOException {
-        if (transparentGzip && responseHeaders.isContentEncodingGzip()) {
-            /*
-             * If the response was transparently gzipped, remove the gzip header field
-             * so clients don't double decompress. http://b/3009828
-             *
-             * Also remove the Content-Length in this case because it contains the length
-             * of the gzipped response. This isn't terribly useful and is dangerous because
-             * clients can query the content length, but not the content encoding.
-             */
-            responseHeaders.stripContentEncoding();
-            responseHeaders.stripContentLength();
-            responseBodyIn = new GZIPInputStream(transferStream);
-        } else {
-            responseBodyIn = transferStream;
-        }
-    }
-
-    private InputStream getTransferStream() throws IOException {
-        if (!hasResponseBody()) {
-            return new FixedLengthInputStream(socketIn, cacheRequest, this, 0);
-        }
-
-        if (responseHeaders.isChunked()) {
-            return new ChunkedInputStream(socketIn, cacheRequest, this);
-        }
-
-        if (responseHeaders.getContentLength() != -1) {
-            return new FixedLengthInputStream(socketIn, cacheRequest, this,
-                    responseHeaders.getContentLength());
-        }
-
-        /*
-         * Wrap the input stream from the HttpConnection (rather than
-         * just returning "socketIn" directly here), so that we can control
-         * its use after the reference escapes.
-         */
-        return new UnknownLengthHttpInputStream(socketIn, cacheRequest, this);
-    }
-
-    private void readResponseHeaders() throws IOException {
-        RawHeaders headers;
-        do {
-            headers = new RawHeaders();
-            headers.setStatusLine(Streams.readAsciiLine(socketIn));
-            readHeaders(headers);
-        } while (headers.getResponseCode() == HTTP_CONTINUE);
-        setResponse(new ResponseHeaders(uri, headers), null);
-    }
-
-    /**
-     * Returns true if the response must have a (possibly 0-length) body.
-     * See RFC 2616 section 4.3.
-     */
-    public final boolean hasResponseBody() {
-        int responseCode = responseHeaders.getHeaders().getResponseCode();
-
-        // HEAD requests never yield a body regardless of the response headers.
-        if (method == HEAD) {
-            return false;
-        }
-
-        if (method != CONNECT
-                && (responseCode < HTTP_CONTINUE || responseCode >= 200)
-                && responseCode != HttpURLConnectionImpl.HTTP_NO_CONTENT
-                && responseCode != HttpURLConnectionImpl.HTTP_NOT_MODIFIED) {
-            return true;
-        }
-
-        /*
-         * If the Content-Length or Transfer-Encoding headers disagree with the
-         * response code, the response is malformed. For best compatibility, we
-         * honor the headers.
-         */
-        if (responseHeaders.getContentLength() != -1 || responseHeaders.isChunked()) {
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Trailers are headers included after the last chunk of a response encoded
-     * with chunked encoding.
-     */
-    final void readTrailers() throws IOException {
-        readHeaders(responseHeaders.getHeaders());
-    }
-
-    private void readHeaders(RawHeaders headers) throws IOException {
-        // parse the result headers until the first blank line
-        String line;
-        while (!(line = Streams.readAsciiLine(socketIn)).isEmpty()) {
-            headers.addLine(line);
-        }
-
-        CookieHandler cookieHandler = CookieHandler.getDefault();
-        if (cookieHandler != null) {
-            cookieHandler.put(uri, headers.toMultimap());
-        }
-    }
-
-    /**
-     * Prepares the HTTP headers and sends them to the server.
-     *
-     * <p>For streaming requests with a body, headers must be prepared
-     * <strong>before</strong> the output stream has been written to. Otherwise
-     * the body would need to be buffered!
-     *
-     * <p>For non-streaming requests with a body, headers must be prepared
-     * <strong>after</strong> the output stream has been written to and closed.
-     * This ensures that the {@code Content-Length} header field receives the
-     * proper value.
-     *
-     * @param contentLength the number of bytes in the request body, or -1 if
-     *      the request body length is unknown.
-     */
-    private void writeRequestHeaders(int contentLength) throws IOException {
-        if (sentRequestMillis != -1) {
-            throw new IllegalStateException();
-        }
-
-        RawHeaders headersToSend = getNetworkRequestHeaders();
-        byte[] bytes = headersToSend.toHeaderString().getBytes(Charsets.ISO_8859_1);
-
-        if (contentLength != -1 && bytes.length + contentLength <= MAX_REQUEST_BUFFER_LENGTH) {
-            requestOut = new BufferedOutputStream(socketOut, bytes.length + contentLength);
-        }
-
-        sentRequestMillis = System.currentTimeMillis();
-        requestOut.write(bytes);
-    }
-
-    /**
-     * Returns the headers to send on a network request.
-     *
-     * <p>This adds the content length and content-type headers, which are
-     * neither needed nor known when querying the response cache.
-     *
-     * <p>It updates the status line, which may need to be fully qualified if
-     * the connection is using a proxy.
-     */
-    protected RawHeaders getNetworkRequestHeaders() throws IOException {
-        requestHeaders.getHeaders().setStatusLine(getRequestLine());
-
-        int fixedContentLength = policy.getFixedContentLength();
-        if (fixedContentLength != -1) {
-            requestHeaders.setContentLength(fixedContentLength);
-        } else if (sendChunked) {
-            requestHeaders.setChunked();
-        } else if (requestBodyOut instanceof RetryableOutputStream) {
-            int contentLength = ((RetryableOutputStream) requestBodyOut).contentLength();
-            requestHeaders.setContentLength(contentLength);
-        }
-
-        return requestHeaders.getHeaders();
-    }
-
-    /**
-     * Populates requestHeaders with defaults and cookies.
-     *
-     * <p>This client doesn't specify a default {@code Accept} header because it
-     * doesn't know what content types the application is interested in.
-     */
-    private void prepareRawRequestHeaders() throws IOException {
-        requestHeaders.getHeaders().setStatusLine(getRequestLine());
-
-        if (requestHeaders.getUserAgent() == null) {
-            requestHeaders.setUserAgent(getDefaultUserAgent());
-        }
-
-        if (requestHeaders.getHost() == null) {
-            requestHeaders.setHost(getOriginAddress(policy.getURL()));
-        }
-
-        if (httpMinorVersion > 0 && requestHeaders.getConnection() == null) {
-            requestHeaders.setConnection("Keep-Alive");
-        }
-
-        if (requestHeaders.getAcceptEncoding() == null) {
-            transparentGzip = true;
-            requestHeaders.setAcceptEncoding("gzip");
-        }
-
-        if (hasRequestBody() && requestHeaders.getContentType() == null) {
-            requestHeaders.setContentType("application/x-www-form-urlencoded");
-        }
-
-        long ifModifiedSince = policy.getIfModifiedSince();
-        if (ifModifiedSince != 0) {
-            requestHeaders.setIfModifiedSince(new Date(ifModifiedSince));
-        }
-
-        CookieHandler cookieHandler = CookieHandler.getDefault();
-        if (cookieHandler != null) {
-            requestHeaders.addCookies(
-                    cookieHandler.get(uri, requestHeaders.getHeaders().toMultimap()));
-        }
-    }
-
-    private String getRequestLine() {
-        String protocol = (httpMinorVersion == 0) ? "HTTP/1.0" : "HTTP/1.1";
-        return method + " " + requestString() + " " + protocol;
-    }
-
-    private String requestString() {
-        URL url = policy.getURL();
-        if (includeAuthorityInRequestLine()) {
-            return url.toString();
-        } else {
-            String fileOnly = url.getFile();
-            if (fileOnly == null) {
-                fileOnly = "/";
-            } else if (!fileOnly.startsWith("/")) {
-                fileOnly = "/" + fileOnly;
-            }
-            return fileOnly;
-        }
-    }
-
-    /**
-     * Returns true if the request line should contain the full URL with host
-     * and port (like "GET http://android.com/foo HTTP/1.1") or only the path
-     * (like "GET /foo HTTP/1.1").
-     *
-     * <p>This is non-final because for HTTPS it's never necessary to supply the
-     * full URL, even if a proxy is in use.
-     */
-    protected boolean includeAuthorityInRequestLine() {
-        return policy.usingProxy();
-    }
-
-    /**
-     * Returns the SSL configuration for connections created by this engine.
-     * We cannot reuse HTTPS connections if the socket factory has changed.
-     */
-    protected SSLSocketFactory getSslSocketFactory() {
-        return null;
-    }
-
-    protected final String getDefaultUserAgent() {
-        String agent = System.getProperty("http.agent");
-        return agent != null ? agent : ("Java" + System.getProperty("java.version"));
-    }
-
-    protected final String getOriginAddress(URL url) {
-        int port = url.getPort();
-        String result = url.getHost();
-        if (port > 0 && port != policy.getDefaultPort()) {
-            result = result + ":" + port;
-        }
-        return result;
-    }
-
-    protected boolean requiresTunnel() {
-        return false;
-    }
-
-    /**
-     * Flushes the remaining request header and body, parses the HTTP response
-     * headers and starts reading the HTTP response body if it exists.
-     */
-    public final void readResponse() throws IOException {
-        if (hasResponse()) {
-            return;
-        }
-
-        if (responseSource == null) {
-            throw new IllegalStateException("readResponse() without sendRequest()");
-        }
-
-        if (!responseSource.requiresConnection()) {
-            return;
-        }
-
-        if (sentRequestMillis == -1) {
-            int contentLength = requestBodyOut instanceof RetryableOutputStream
-                    ? ((RetryableOutputStream) requestBodyOut).contentLength()
-                    : -1;
-            writeRequestHeaders(contentLength);
-        }
-
-        if (requestBodyOut != null) {
-            requestBodyOut.close();
-            if (requestBodyOut instanceof RetryableOutputStream) {
-                ((RetryableOutputStream) requestBodyOut).writeToSocket(requestOut);
-            }
-        }
-
-        requestOut.flush();
-        requestOut = socketOut;
-
-        readResponseHeaders();
-        responseHeaders.setLocalTimestamps(sentRequestMillis, System.currentTimeMillis());
-
-        if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
-            if (cachedResponseHeaders.validate(responseHeaders)) {
-                release(true);
-                ResponseHeaders combinedHeaders = cachedResponseHeaders.combine(responseHeaders);
-                setResponse(combinedHeaders, cachedResponseBody);
-                if (responseCache instanceof ExtendedResponseCache) {
-                    ExtendedResponseCache httpResponseCache = (ExtendedResponseCache) responseCache;
-                    httpResponseCache.trackConditionalCacheHit();
-                    httpResponseCache.update(cacheResponse, getHttpConnectionToCache());
-                }
-                return;
-            } else {
-                IoUtils.closeQuietly(cachedResponseBody);
-            }
-        }
-
-        if (hasResponseBody()) {
-            maybeCache(); // reentrant. this calls into user code which may call back into this!
-        }
-
-        initContentStream(getTransferStream());
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpHandler.java b/luni/src/main/java/libcore/net/http/HttpHandler.java
deleted file mode 100644
index e168f42..0000000
--- a/luni/src/main/java/libcore/net/http/HttpHandler.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.IOException;
-import java.net.Proxy;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLStreamHandler;
-
-public final class HttpHandler extends URLStreamHandler {
-
-    @Override protected URLConnection openConnection(URL u) throws IOException {
-        return new HttpURLConnectionImpl(u, getDefaultPort());
-    }
-
-    @Override protected URLConnection openConnection(URL url, Proxy proxy) throws IOException {
-        if (url == null || proxy == null) {
-            throw new IllegalArgumentException("url == null || proxy == null");
-        }
-        return new HttpURLConnectionImpl(url, getDefaultPort(), proxy);
-    }
-
-    @Override protected int getDefaultPort() {
-        return 80;
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpResponseCache.java b/luni/src/main/java/libcore/net/http/HttpResponseCache.java
deleted file mode 100644
index 1a9dfd1..0000000
--- a/luni/src/main/java/libcore/net/http/HttpResponseCache.java
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.BufferedWriter;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FilterInputStream;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.net.CacheRequest;
-import java.net.CacheResponse;
-import java.net.ExtendedResponseCache;
-import java.net.HttpURLConnection;
-import java.net.ResponseCache;
-import java.net.ResponseSource;
-import java.net.SecureCacheResponse;
-import java.net.URI;
-import java.net.URLConnection;
-import java.nio.charset.Charsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import libcore.io.Base64;
-import libcore.io.DiskLruCache;
-import libcore.io.IoUtils;
-import libcore.io.StrictLineReader;
-
-/**
- * Cache responses in a directory on the file system. Most clients should use
- * {@code android.net.HttpResponseCache}, the stable, documented front end for
- * this.
- */
-public final class HttpResponseCache extends ResponseCache implements ExtendedResponseCache {
-    // TODO: add APIs to iterate the cache?
-    private static final int VERSION = 201105;
-    private static final int ENTRY_METADATA = 0;
-    private static final int ENTRY_BODY = 1;
-    private static final int ENTRY_COUNT = 2;
-
-    private final DiskLruCache cache;
-
-    /* read and write statistics, all guarded by 'this' */
-    private int writeSuccessCount;
-    private int writeAbortCount;
-    private int networkCount;
-    private int hitCount;
-    private int requestCount;
-
-    public HttpResponseCache(File directory, long maxSize) throws IOException {
-        cache = DiskLruCache.open(directory, VERSION, ENTRY_COUNT, maxSize);
-    }
-
-    private String uriToKey(URI uri) {
-        try {
-            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
-            byte[] md5bytes = messageDigest.digest(uri.toString().getBytes(Charsets.UTF_8));
-            return IntegralToString.bytesToHexString(md5bytes, false);
-        } catch (NoSuchAlgorithmException e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    @Override public CacheResponse get(URI uri, String requestMethod,
-            Map<String, List<String>> requestHeaders) {
-        String key = uriToKey(uri);
-        DiskLruCache.Snapshot snapshot;
-        Entry entry;
-        try {
-            snapshot = cache.get(key);
-            if (snapshot == null) {
-                return null;
-            }
-            entry = new Entry(snapshot.getInputStream(ENTRY_METADATA));
-        } catch (IOException e) {
-            // Give up because the cache cannot be read.
-            return null;
-        }
-
-        if (!entry.matches(uri, requestMethod, requestHeaders)) {
-            snapshot.close();
-            return null;
-        }
-
-        return entry.isHttps()
-                ? new EntrySecureCacheResponse(entry, snapshot)
-                : new EntryCacheResponse(entry, snapshot);
-    }
-
-    @Override public CacheRequest put(URI uri, URLConnection urlConnection) throws IOException {
-        if (!(urlConnection instanceof HttpURLConnection)) {
-            return null;
-        }
-
-        HttpURLConnection httpConnection = (HttpURLConnection) urlConnection;
-        String requestMethod = httpConnection.getRequestMethod();
-        String key = uriToKey(uri);
-
-        if (requestMethod.equals(HttpEngine.POST)
-                || requestMethod.equals(HttpEngine.PUT)
-                || requestMethod.equals(HttpEngine.DELETE)) {
-            try {
-                cache.remove(key);
-            } catch (IOException ignored) {
-                // The cache cannot be written.
-            }
-            return null;
-        } else if (!requestMethod.equals(HttpEngine.GET)) {
-            /*
-             * Don't cache non-GET responses. We're technically allowed to cache
-             * HEAD requests and some POST requests, but the complexity of doing
-             * so is high and the benefit is low.
-             */
-            return null;
-        }
-
-        HttpEngine httpEngine = getHttpEngine(httpConnection);
-        if (httpEngine == null) {
-            // Don't cache unless the HTTP implementation is ours.
-            return null;
-        }
-
-        ResponseHeaders response = httpEngine.getResponseHeaders();
-        if (response.hasVaryAll()) {
-            return null;
-        }
-
-        RawHeaders varyHeaders = httpEngine.getRequestHeaders().getHeaders().getAll(
-                response.getVaryFields());
-        Entry entry = new Entry(uri, varyHeaders, httpConnection);
-        DiskLruCache.Editor editor = null;
-        try {
-            editor = cache.edit(key);
-            if (editor == null) {
-                return null;
-            }
-            entry.writeTo(editor);
-            return new CacheRequestImpl(editor);
-        } catch (IOException e) {
-            abortQuietly(editor);
-            return null;
-        }
-    }
-
-    /**
-     * Handles a conditional request hit by updating the stored cache response
-     * with the headers from {@code httpConnection}. The cached response body is
-     * not updated. If the stored response has changed since {@code
-     * conditionalCacheHit} was returned, this does nothing.
-     */
-    public void update(CacheResponse conditionalCacheHit, HttpURLConnection httpConnection) {
-        HttpEngine httpEngine = getHttpEngine(httpConnection);
-        URI uri = httpEngine.getUri();
-        ResponseHeaders response = httpEngine.getResponseHeaders();
-        RawHeaders varyHeaders = httpEngine.getRequestHeaders().getHeaders()
-                .getAll(response.getVaryFields());
-        Entry entry = new Entry(uri, varyHeaders, httpConnection);
-        DiskLruCache.Snapshot snapshot = (conditionalCacheHit instanceof EntryCacheResponse)
-                ? ((EntryCacheResponse) conditionalCacheHit).snapshot
-                : ((EntrySecureCacheResponse) conditionalCacheHit).snapshot;
-        DiskLruCache.Editor editor = null;
-        try {
-            editor = snapshot.edit(); // returns null if snapshot is not current
-            if (editor != null) {
-                entry.writeTo(editor);
-                editor.commit();
-            }
-        } catch (IOException e) {
-            abortQuietly(editor);
-        }
-    }
-
-    private void abortQuietly(DiskLruCache.Editor editor) {
-        // Give up because the cache cannot be written.
-        try {
-            if (editor != null) {
-                editor.abort();
-            }
-        } catch (IOException ignored) {
-        }
-    }
-
-    private HttpEngine getHttpEngine(HttpURLConnection httpConnection) {
-        if (httpConnection instanceof HttpURLConnectionImpl) {
-            return ((HttpURLConnectionImpl) httpConnection).getHttpEngine();
-        } else if (httpConnection instanceof HttpsURLConnectionImpl) {
-            return ((HttpsURLConnectionImpl) httpConnection).getHttpEngine();
-        } else {
-            return null;
-        }
-    }
-
-    public DiskLruCache getCache() {
-        return cache;
-    }
-
-    public synchronized int getWriteAbortCount() {
-        return writeAbortCount;
-    }
-
-    public synchronized int getWriteSuccessCount() {
-        return writeSuccessCount;
-    }
-
-    public synchronized void trackResponse(ResponseSource source) {
-        requestCount++;
-
-        switch (source) {
-        case CACHE:
-            hitCount++;
-            break;
-        case CONDITIONAL_CACHE:
-        case NETWORK:
-            networkCount++;
-            break;
-        }
-    }
-
-    public synchronized void trackConditionalCacheHit() {
-        hitCount++;
-    }
-
-    public synchronized int getNetworkCount() {
-        return networkCount;
-    }
-
-    public synchronized int getHitCount() {
-        return hitCount;
-    }
-
-    public synchronized int getRequestCount() {
-        return requestCount;
-    }
-
-    private final class CacheRequestImpl extends CacheRequest {
-        private final DiskLruCache.Editor editor;
-        private OutputStream cacheOut;
-        private boolean done;
-        private OutputStream body;
-
-        public CacheRequestImpl(final DiskLruCache.Editor editor) throws IOException {
-            this.editor = editor;
-            this.cacheOut = editor.newOutputStream(ENTRY_BODY);
-            this.body = new FilterOutputStream(cacheOut) {
-                @Override public void close() throws IOException {
-                    synchronized (HttpResponseCache.this) {
-                        if (done) {
-                            return;
-                        }
-                        done = true;
-                        writeSuccessCount++;
-                    }
-                    super.close();
-                    editor.commit();
-                }
-
-                @Override
-                public void write(byte[] buffer, int offset, int length) throws IOException {
-                    // Since we don't override "write(int oneByte)", we can write directly to "out"
-                    // and avoid the inefficient implementation from the FilterOutputStream.
-                    out.write(buffer, offset, length);
-                }
-            };
-        }
-
-        @Override public void abort() {
-            synchronized (HttpResponseCache.this) {
-                if (done) {
-                    return;
-                }
-                done = true;
-                writeAbortCount++;
-            }
-            IoUtils.closeQuietly(cacheOut);
-            try {
-                editor.abort();
-            } catch (IOException ignored) {
-            }
-        }
-
-        @Override public OutputStream getBody() throws IOException {
-            return body;
-        }
-    }
-
-    private static final class Entry {
-        private final String uri;
-        private final RawHeaders varyHeaders;
-        private final String requestMethod;
-        private final RawHeaders responseHeaders;
-        private final String cipherSuite;
-        private final Certificate[] peerCertificates;
-        private final Certificate[] localCertificates;
-
-        /*
-         * Reads an entry from an input stream. A typical entry looks like this:
-         *   http://google.com/foo
-         *   GET
-         *   2
-         *   Accept-Language: fr-CA
-         *   Accept-Charset: UTF-8
-         *   HTTP/1.1 200 OK
-         *   3
-         *   Content-Type: image/png
-         *   Content-Length: 100
-         *   Cache-Control: max-age=600
-         *
-         * A typical HTTPS file looks like this:
-         *   https://google.com/foo
-         *   GET
-         *   2
-         *   Accept-Language: fr-CA
-         *   Accept-Charset: UTF-8
-         *   HTTP/1.1 200 OK
-         *   3
-         *   Content-Type: image/png
-         *   Content-Length: 100
-         *   Cache-Control: max-age=600
-         *
-         *   AES_256_WITH_MD5
-         *   2
-         *   base64-encoded peerCertificate[0]
-         *   base64-encoded peerCertificate[1]
-         *   -1
-         *
-         * The file is newline separated. The first two lines are the URL and
-         * the request method. Next is the number of HTTP Vary request header
-         * lines, followed by those lines.
-         *
-         * Next is the response status line, followed by the number of HTTP
-         * response header lines, followed by those lines.
-         *
-         * HTTPS responses also contain SSL session information. This begins
-         * with a blank line, and then a line containing the cipher suite. Next
-         * is the length of the peer certificate chain. These certificates are
-         * base64-encoded and appear each on their own line. The next line
-         * contains the length of the local certificate chain. These
-         * certificates are also base64-encoded and appear each on their own
-         * line. A length of -1 is used to encode a null array.
-         */
-        public Entry(InputStream in) throws IOException {
-            try {
-                StrictLineReader reader = new StrictLineReader(in, Charsets.US_ASCII);
-                uri = reader.readLine();
-                requestMethod = reader.readLine();
-                varyHeaders = new RawHeaders();
-                int varyRequestHeaderLineCount = reader.readInt();
-                for (int i = 0; i < varyRequestHeaderLineCount; i++) {
-                    varyHeaders.addLine(reader.readLine());
-                }
-
-                responseHeaders = new RawHeaders();
-                responseHeaders.setStatusLine(reader.readLine());
-                int responseHeaderLineCount = reader.readInt();
-                for (int i = 0; i < responseHeaderLineCount; i++) {
-                    responseHeaders.addLine(reader.readLine());
-                }
-
-                if (isHttps()) {
-                    String blank = reader.readLine();
-                    if (!blank.isEmpty()) {
-                        throw new IOException("expected \"\" but was \"" + blank + "\"");
-                    }
-                    cipherSuite = reader.readLine();
-                    peerCertificates = readCertArray(reader);
-                    localCertificates = readCertArray(reader);
-                } else {
-                    cipherSuite = null;
-                    peerCertificates = null;
-                    localCertificates = null;
-                }
-            } finally {
-                in.close();
-            }
-        }
-
-        public Entry(URI uri, RawHeaders varyHeaders, HttpURLConnection httpConnection) {
-            this.uri = uri.toString();
-            this.varyHeaders = varyHeaders;
-            this.requestMethod = httpConnection.getRequestMethod();
-            this.responseHeaders = RawHeaders.fromMultimap(httpConnection.getHeaderFields());
-
-            if (isHttps()) {
-                HttpsURLConnection httpsConnection = (HttpsURLConnection) httpConnection;
-                cipherSuite = httpsConnection.getCipherSuite();
-                Certificate[] peerCertificatesNonFinal = null;
-                try {
-                    peerCertificatesNonFinal = httpsConnection.getServerCertificates();
-                } catch (SSLPeerUnverifiedException ignored) {
-                }
-                peerCertificates = peerCertificatesNonFinal;
-                localCertificates = httpsConnection.getLocalCertificates();
-            } else {
-                cipherSuite = null;
-                peerCertificates = null;
-                localCertificates = null;
-            }
-        }
-
-        public void writeTo(DiskLruCache.Editor editor) throws IOException {
-            OutputStream out = editor.newOutputStream(ENTRY_METADATA);
-            Writer writer = new BufferedWriter(new OutputStreamWriter(out, Charsets.UTF_8));
-
-            writer.write(uri + '\n');
-            writer.write(requestMethod + '\n');
-            writer.write(Integer.toString(varyHeaders.length()) + '\n');
-            for (int i = 0; i < varyHeaders.length(); i++) {
-                writer.write(varyHeaders.getFieldName(i) + ": "
-                        + varyHeaders.getValue(i) + '\n');
-            }
-
-            writer.write(responseHeaders.getStatusLine() + '\n');
-            writer.write(Integer.toString(responseHeaders.length()) + '\n');
-            for (int i = 0; i < responseHeaders.length(); i++) {
-                writer.write(responseHeaders.getFieldName(i) + ": "
-                        + responseHeaders.getValue(i) + '\n');
-            }
-
-            if (isHttps()) {
-                writer.write('\n');
-                writer.write(cipherSuite + '\n');
-                writeCertArray(writer, peerCertificates);
-                writeCertArray(writer, localCertificates);
-            }
-            writer.close();
-        }
-
-        private boolean isHttps() {
-            return uri.startsWith("https://");
-        }
-
-        private Certificate[] readCertArray(StrictLineReader reader) throws IOException {
-            int length = reader.readInt();
-            if (length == -1) {
-                return null;
-            }
-            try {
-                CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
-                Certificate[] result = new Certificate[length];
-                for (int i = 0; i < result.length; i++) {
-                    String line = reader.readLine();
-                    byte[] bytes = Base64.decode(line.getBytes(Charsets.US_ASCII));
-                    result[i] = certificateFactory.generateCertificate(
-                            new ByteArrayInputStream(bytes));
-                }
-                return result;
-            } catch (CertificateException e) {
-                throw new IOException(e);
-            }
-        }
-
-        private void writeCertArray(Writer writer, Certificate[] certificates) throws IOException {
-            if (certificates == null) {
-                writer.write("-1\n");
-                return;
-            }
-            try {
-                writer.write(Integer.toString(certificates.length) + '\n');
-                for (Certificate certificate : certificates) {
-                    byte[] bytes = certificate.getEncoded();
-                    String line = Base64.encode(bytes);
-                    writer.write(line + '\n');
-                }
-            } catch (CertificateEncodingException e) {
-                throw new IOException(e);
-            }
-        }
-
-        public boolean matches(URI uri, String requestMethod,
-                Map<String, List<String>> requestHeaders) {
-            return this.uri.equals(uri.toString())
-                    && this.requestMethod.equals(requestMethod)
-                    && new ResponseHeaders(uri, responseHeaders)
-                            .varyMatches(varyHeaders.toMultimap(), requestHeaders);
-        }
-    }
-
-    /**
-     * Returns an input stream that reads the body of a snapshot, closing the
-     * snapshot when the stream is closed.
-     */
-    private static InputStream newBodyInputStream(final DiskLruCache.Snapshot snapshot) {
-        return new FilterInputStream(snapshot.getInputStream(ENTRY_BODY)) {
-            @Override public void close() throws IOException {
-                snapshot.close();
-                super.close();
-            }
-        };
-    }
-
-    static class EntryCacheResponse extends CacheResponse {
-        private final Entry entry;
-        private final DiskLruCache.Snapshot snapshot;
-        private final InputStream in;
-
-        public EntryCacheResponse(Entry entry, DiskLruCache.Snapshot snapshot) {
-            this.entry = entry;
-            this.snapshot = snapshot;
-            this.in = newBodyInputStream(snapshot);
-        }
-
-        @Override public Map<String, List<String>> getHeaders() {
-            return entry.responseHeaders.toMultimap();
-        }
-
-        @Override public InputStream getBody() {
-            return in;
-        }
-    }
-
-    static class EntrySecureCacheResponse extends SecureCacheResponse {
-        private final Entry entry;
-        private final DiskLruCache.Snapshot snapshot;
-        private final InputStream in;
-
-        public EntrySecureCacheResponse(Entry entry, DiskLruCache.Snapshot snapshot) {
-            this.entry = entry;
-            this.snapshot = snapshot;
-            this.in = newBodyInputStream(snapshot);
-        }
-
-        @Override public Map<String, List<String>> getHeaders() {
-            return entry.responseHeaders.toMultimap();
-        }
-
-        @Override public InputStream getBody() {
-            return in;
-        }
-
-        @Override public String getCipherSuite() {
-            return entry.cipherSuite;
-        }
-
-        @Override public List<Certificate> getServerCertificateChain()
-                throws SSLPeerUnverifiedException {
-            if (entry.peerCertificates == null || entry.peerCertificates.length == 0) {
-                throw new SSLPeerUnverifiedException(null);
-            }
-            return Arrays.asList(entry.peerCertificates.clone());
-        }
-
-        @Override public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
-            if (entry.peerCertificates == null || entry.peerCertificates.length == 0) {
-                throw new SSLPeerUnverifiedException(null);
-            }
-            return ((X509Certificate) entry.peerCertificates[0]).getSubjectX500Principal();
-        }
-
-        @Override public List<Certificate> getLocalCertificateChain() {
-            if (entry.localCertificates == null || entry.localCertificates.length == 0) {
-                return null;
-            }
-            return Arrays.asList(entry.localCertificates.clone());
-        }
-
-        @Override public Principal getLocalPrincipal() {
-            if (entry.localCertificates == null || entry.localCertificates.length == 0) {
-                return null;
-            }
-            return ((X509Certificate) entry.localCertificates[0]).getSubjectX500Principal();
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java b/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java
deleted file mode 100644
index 3e6503f..0000000
--- a/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Authenticator;
-import java.net.HttpRetryException;
-import java.net.HttpURLConnection;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.PasswordAuthentication;
-import java.net.ProtocolException;
-import java.net.Proxy;
-import java.net.SocketPermission;
-import java.net.URL;
-import java.nio.charset.Charsets;
-import java.security.Permission;
-import java.util.List;
-import java.util.Map;
-import libcore.io.Base64;
-import libcore.io.IoUtils;
-
-/**
- * This implementation uses HttpEngine to send requests and receive responses.
- * This class may use multiple HttpEngines to follow redirects, authentication
- * retries, etc. to retrieve the final response body.
- *
- * <h3>What does 'connected' mean?</h3>
- * This class inherits a {@code connected} field from the superclass. That field
- * is <strong>not</strong> used to indicate not whether this URLConnection is
- * currently connected. Instead, it indicates whether a connection has ever been
- * attempted. Once a connection has been attempted, certain properties (request
- * header fields, request method, etc.) are immutable. Test the {@code
- * connection} field on this class for null/non-null to determine of an instance
- * is currently connected to a server.
- */
-class HttpURLConnectionImpl extends HttpURLConnection {
-
-    private final int defaultPort;
-
-    private Proxy proxy;
-
-    private final RawHeaders rawRequestHeaders = new RawHeaders();
-
-    private int redirectionCount;
-
-    protected IOException httpEngineFailure;
-    protected HttpEngine httpEngine;
-
-    protected HttpURLConnectionImpl(URL url, int port) {
-        super(url);
-        defaultPort = port;
-    }
-
-    protected HttpURLConnectionImpl(URL url, int port, Proxy proxy) {
-        this(url, port);
-        this.proxy = proxy;
-    }
-
-    @Override public final void connect() throws IOException {
-        initHttpEngine();
-        try {
-            httpEngine.sendRequest();
-        } catch (IOException e) {
-            httpEngineFailure = e;
-            throw e;
-        }
-    }
-
-    @Override public final void disconnect() {
-        // Calling disconnect() before a connection exists should have no effect.
-        if (httpEngine != null) {
-            // We close the response body here instead of in
-            // HttpEngine.release because that is called when input
-            // has been completely read from the underlying socket.
-            // However the response body can be a GZIPInputStream that
-            // still has unread data.
-            if (httpEngine.hasResponse()) {
-                IoUtils.closeQuietly(httpEngine.getResponseBody());
-            }
-            httpEngine.release(false);
-        }
-    }
-
-    /**
-     * Returns an input stream from the server in the case of error such as the
-     * requested file (txt, htm, html) is not found on the remote server.
-     */
-    @Override public final InputStream getErrorStream() {
-        try {
-            HttpEngine response = getResponse();
-            if (response.hasResponseBody()
-                    && response.getResponseCode() >= HTTP_BAD_REQUEST) {
-                return response.getResponseBody();
-            }
-            return null;
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Returns the value of the field at {@code position}. Returns null if there
-     * are fewer than {@code position} headers.
-     */
-    @Override public final String getHeaderField(int position) {
-        try {
-            return getResponse().getResponseHeaders().getHeaders().getValue(position);
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Returns the value of the field corresponding to the {@code fieldName}, or
-     * null if there is no such field. If the field has multiple values, the
-     * last value is returned.
-     */
-    @Override public final String getHeaderField(String fieldName) {
-        try {
-            RawHeaders rawHeaders = getResponse().getResponseHeaders().getHeaders();
-            return fieldName == null
-                    ? rawHeaders.getStatusLine()
-                    : rawHeaders.get(fieldName);
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    @Override public final String getHeaderFieldKey(int position) {
-        try {
-            return getResponse().getResponseHeaders().getHeaders().getFieldName(position);
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    @Override public final Map<String, List<String>> getHeaderFields() {
-        try {
-            return getResponse().getResponseHeaders().getHeaders().toMultimap();
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    @Override public final Map<String, List<String>> getRequestProperties() {
-        if (connected) {
-            throw new IllegalStateException(
-                    "Cannot access request header fields after connection is set");
-        }
-        return rawRequestHeaders.toMultimap();
-    }
-
-    @Override public final InputStream getInputStream() throws IOException {
-        if (!doInput) {
-            throw new ProtocolException("This protocol does not support input");
-        }
-
-        HttpEngine response = getResponse();
-
-        /*
-         * if the requested file does not exist, throw an exception formerly the
-         * Error page from the server was returned if the requested file was
-         * text/html this has changed to return FileNotFoundException for all
-         * file types
-         */
-        if (getResponseCode() >= HTTP_BAD_REQUEST) {
-            throw new FileNotFoundException(url.toString());
-        }
-
-        InputStream result = response.getResponseBody();
-        if (result == null) {
-            throw new IOException("No response body exists; responseCode=" + getResponseCode());
-        }
-        return result;
-    }
-
-    @Override public final OutputStream getOutputStream() throws IOException {
-        connect();
-
-        OutputStream result = httpEngine.getRequestBody();
-        if (result == null) {
-            throw new ProtocolException("method does not support a request body: " + method);
-        } else if (httpEngine.hasResponse()) {
-            throw new ProtocolException("cannot write request body after response has been read");
-        }
-
-        return result;
-    }
-
-    @Override public final Permission getPermission() throws IOException {
-        String connectToAddress = getConnectToHost() + ":" + getConnectToPort();
-        return new SocketPermission(connectToAddress, "connect, resolve");
-    }
-
-    private String getConnectToHost() {
-        return usingProxy()
-                ? ((InetSocketAddress) proxy.address()).getHostName()
-                : getURL().getHost();
-    }
-
-    private int getConnectToPort() {
-        int hostPort = usingProxy()
-                ? ((InetSocketAddress) proxy.address()).getPort()
-                : getURL().getPort();
-        return hostPort < 0 ? getDefaultPort() : hostPort;
-    }
-
-    @Override public final String getRequestProperty(String field) {
-        if (field == null) {
-            return null;
-        }
-        return rawRequestHeaders.get(field);
-    }
-
-    private void initHttpEngine() throws IOException {
-        if (httpEngineFailure != null) {
-            throw httpEngineFailure;
-        } else if (httpEngine != null) {
-            return;
-        }
-
-        connected = true;
-        try {
-            if (doOutput) {
-                if (method == HttpEngine.GET) {
-                    // they are requesting a stream to write to. This implies a POST method
-                    method = HttpEngine.POST;
-                } else if (method != HttpEngine.POST && method != HttpEngine.PUT) {
-                    // If the request method is neither POST nor PUT, then you're not writing
-                    throw new ProtocolException(method + " does not support writing");
-                }
-            }
-            httpEngine = newHttpEngine(method, rawRequestHeaders, null, null);
-        } catch (IOException e) {
-            httpEngineFailure = e;
-            throw e;
-        }
-    }
-
-    /**
-     * Create a new HTTP engine. This hook method is non-final so it can be
-     * overridden by HttpsURLConnectionImpl.
-     */
-    protected HttpEngine newHttpEngine(String method, RawHeaders requestHeaders,
-            HttpConnection connection, RetryableOutputStream requestBody) throws IOException {
-        return new HttpEngine(this, method, requestHeaders, connection, requestBody);
-    }
-
-    /**
-     * Aggressively tries to get the final HTTP response, potentially making
-     * many HTTP requests in the process in order to cope with redirects and
-     * authentication.
-     */
-    private HttpEngine getResponse() throws IOException {
-        initHttpEngine();
-
-        if (httpEngine.hasResponse()) {
-            return httpEngine;
-        }
-
-        while (true) {
-            try {
-                httpEngine.sendRequest();
-                httpEngine.readResponse();
-            } catch (IOException e) {
-                /*
-                 * If the connection was recycled, its staleness may have caused
-                 * the failure. Silently retry with a different connection.
-                 */
-                OutputStream requestBody = httpEngine.getRequestBody();
-                if (httpEngine.hasRecycledConnection()
-                        && (requestBody == null || requestBody instanceof RetryableOutputStream)) {
-                    httpEngine.release(false);
-                    httpEngine = newHttpEngine(method, rawRequestHeaders, null,
-                            (RetryableOutputStream) requestBody);
-                    continue;
-                }
-                httpEngineFailure = e;
-                throw e;
-            }
-
-            Retry retry = processResponseHeaders();
-            if (retry == Retry.NONE) {
-                httpEngine.automaticallyReleaseConnectionToPool();
-                return httpEngine;
-            }
-
-            /*
-             * The first request was insufficient. Prepare for another...
-             */
-            String retryMethod = method;
-            OutputStream requestBody = httpEngine.getRequestBody();
-
-            /*
-             * Although RFC 2616 10.3.2 specifies that a HTTP_MOVED_PERM
-             * redirect should keep the same method, Chrome, Firefox and the
-             * RI all issue GETs when following any redirect.
-             */
-            int responseCode = getResponseCode();
-            if (responseCode == HTTP_MULT_CHOICE || responseCode == HTTP_MOVED_PERM
-                    || responseCode == HTTP_MOVED_TEMP || responseCode == HTTP_SEE_OTHER) {
-                retryMethod = HttpEngine.GET;
-                requestBody = null;
-            }
-
-            if (requestBody != null && !(requestBody instanceof RetryableOutputStream)) {
-                throw new HttpRetryException("Cannot retry streamed HTTP body",
-                        httpEngine.getResponseCode());
-            }
-
-            if (retry == Retry.DIFFERENT_CONNECTION) {
-                httpEngine.automaticallyReleaseConnectionToPool();
-            } else {
-                httpEngine.markConnectionAsRecycled();
-            }
-
-            httpEngine.release(true);
-
-            httpEngine = newHttpEngine(retryMethod, rawRequestHeaders,
-                    httpEngine.getConnection(), (RetryableOutputStream) requestBody);
-        }
-    }
-
-    HttpEngine getHttpEngine() {
-        return httpEngine;
-    }
-
-    enum Retry {
-        NONE,
-        SAME_CONNECTION,
-        DIFFERENT_CONNECTION
-    }
-
-    /**
-     * Returns the retry action to take for the current response headers. The
-     * headers, proxy and target URL or this connection may be adjusted to
-     * prepare for a follow up request.
-     */
-    private Retry processResponseHeaders() throws IOException {
-        switch (getResponseCode()) {
-        case HTTP_PROXY_AUTH:
-            if (!usingProxy()) {
-                throw new IOException(
-                        "Received HTTP_PROXY_AUTH (407) code while not using proxy");
-            }
-            // fall-through
-        case HTTP_UNAUTHORIZED:
-            boolean credentialsFound = processAuthHeader(getResponseCode(),
-                    httpEngine.getResponseHeaders(), rawRequestHeaders);
-            return credentialsFound ? Retry.SAME_CONNECTION : Retry.NONE;
-
-        case HTTP_MULT_CHOICE:
-        case HTTP_MOVED_PERM:
-        case HTTP_MOVED_TEMP:
-        case HTTP_SEE_OTHER:
-            if (!getInstanceFollowRedirects()) {
-                return Retry.NONE;
-            }
-            if (++redirectionCount > HttpEngine.MAX_REDIRECTS) {
-                throw new ProtocolException("Too many redirects");
-            }
-            String location = getHeaderField("Location");
-            if (location == null) {
-                return Retry.NONE;
-            }
-            URL previousUrl = url;
-            url = new URL(previousUrl, location);
-            if (!previousUrl.getProtocol().equals(url.getProtocol())) {
-                return Retry.NONE; // the scheme changed; don't retry.
-            }
-            if (previousUrl.getHost().equals(url.getHost())
-                    && previousUrl.getEffectivePort() == url.getEffectivePort()) {
-                return Retry.SAME_CONNECTION;
-            } else {
-                return Retry.DIFFERENT_CONNECTION;
-            }
-
-        default:
-            return Retry.NONE;
-        }
-    }
-
-    /**
-     * React to a failed authorization response by looking up new credentials.
-     *
-     * @return true if credentials have been added to successorRequestHeaders
-     *     and another request should be attempted.
-     */
-    final boolean processAuthHeader(int responseCode, ResponseHeaders response,
-            RawHeaders successorRequestHeaders) throws IOException {
-        if (responseCode != HTTP_PROXY_AUTH && responseCode != HTTP_UNAUTHORIZED) {
-            throw new IllegalArgumentException("Bad response code: " + responseCode);
-        }
-
-        // keep asking for username/password until authorized
-        String challengeHeader = responseCode == HTTP_PROXY_AUTH
-                ? "Proxy-Authenticate"
-                : "WWW-Authenticate";
-        String credentials = getAuthorizationCredentials(response.getHeaders(), challengeHeader);
-        if (credentials == null) {
-            return false; // could not find credentials, end request cycle
-        }
-
-        // add authorization credentials, bypassing the already-connected check
-        String fieldName = responseCode == HTTP_PROXY_AUTH
-                ? "Proxy-Authorization"
-                : "Authorization";
-        successorRequestHeaders.set(fieldName, credentials);
-        return true;
-    }
-
-    /**
-     * Returns the authorization credentials on the base of provided challenge.
-     */
-    private String getAuthorizationCredentials(RawHeaders responseHeaders, String challengeHeader)
-            throws IOException {
-        List<Challenge> challenges = HeaderParser.parseChallenges(responseHeaders, challengeHeader);
-        if (challenges.isEmpty()) {
-            throw new IOException("No authentication challenges found");
-        }
-
-        for (Challenge challenge : challenges) {
-            // use the global authenticator to get the password
-            PasswordAuthentication auth = Authenticator.requestPasswordAuthentication(
-                    getConnectToInetAddress(), getConnectToPort(), url.getProtocol(),
-                    challenge.realm, challenge.scheme);
-            if (auth == null) {
-                continue;
-            }
-
-            // base64 encode the username and password
-            String usernameAndPassword = auth.getUserName() + ":" + new String(auth.getPassword());
-            byte[] bytes = usernameAndPassword.getBytes(Charsets.ISO_8859_1);
-            String encoded = Base64.encode(bytes);
-            return challenge.scheme + " " + encoded;
-        }
-
-        return null;
-    }
-
-    private InetAddress getConnectToInetAddress() throws IOException {
-        return usingProxy()
-                ? ((InetSocketAddress) proxy.address()).getAddress()
-                : InetAddress.getByName(getURL().getHost());
-    }
-
-    final int getDefaultPort() {
-        return defaultPort;
-    }
-
-    /** @see HttpURLConnection#setFixedLengthStreamingMode(int) */
-    final int getFixedContentLength() {
-        return fixedContentLength;
-    }
-
-    /** @see HttpURLConnection#setChunkedStreamingMode(int) */
-    final int getChunkLength() {
-        return chunkLength;
-    }
-
-    final Proxy getProxy() {
-        return proxy;
-    }
-
-    final void setProxy(Proxy proxy) {
-        this.proxy = proxy;
-    }
-
-    @Override public final boolean usingProxy() {
-        return (proxy != null && proxy.type() != Proxy.Type.DIRECT);
-    }
-
-    @Override public String getResponseMessage() throws IOException {
-        return getResponse().getResponseHeaders().getHeaders().getResponseMessage();
-    }
-
-    @Override public final int getResponseCode() throws IOException {
-        return getResponse().getResponseCode();
-    }
-
-    @Override public final void setRequestProperty(String field, String newValue) {
-        if (connected) {
-            throw new IllegalStateException("Cannot set request property after connection is made");
-        }
-        if (field == null) {
-            throw new NullPointerException("field == null");
-        }
-        rawRequestHeaders.set(field, newValue);
-    }
-
-    @Override public final void addRequestProperty(String field, String value) {
-        if (connected) {
-            throw new IllegalStateException("Cannot add request property after connection is made");
-        }
-        if (field == null) {
-            throw new NullPointerException("field == null");
-        }
-        rawRequestHeaders.add(field, value);
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpsHandler.java b/luni/src/main/java/libcore/net/http/HttpsHandler.java
deleted file mode 100644
index ed9ba72..0000000
--- a/luni/src/main/java/libcore/net/http/HttpsHandler.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.IOException;
-import java.net.Proxy;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLStreamHandler;
-
-public final class HttpsHandler extends URLStreamHandler {
-
-    @Override protected URLConnection openConnection(URL url) throws IOException {
-        return new HttpsURLConnectionImpl(url, getDefaultPort());
-    }
-
-    @Override protected URLConnection openConnection(URL url, Proxy proxy) throws IOException {
-        if (url == null || proxy == null) {
-            throw new IllegalArgumentException("url == null || proxy == null");
-        }
-        return new HttpsURLConnectionImpl(url, getDefaultPort(), proxy);
-    }
-
-    @Override protected int getDefaultPort() {
-        return 443;
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpsURLConnectionImpl.java b/luni/src/main/java/libcore/net/http/HttpsURLConnectionImpl.java
deleted file mode 100644
index 9e3e4ef..0000000
--- a/luni/src/main/java/libcore/net/http/HttpsURLConnectionImpl.java
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-package libcore.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.CacheResponse;
-import java.net.HttpURLConnection;
-import java.net.ProtocolException;
-import java.net.Proxy;
-import java.net.SecureCacheResponse;
-import java.net.URL;
-import java.security.Permission;
-import java.security.Principal;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.util.List;
-import java.util.Map;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-
-final class HttpsURLConnectionImpl extends HttpsURLConnection {
-
-    /** HttpUrlConnectionDelegate allows reuse of HttpURLConnectionImpl */
-    private final HttpUrlConnectionDelegate delegate;
-
-    protected HttpsURLConnectionImpl(URL url, int port) {
-        super(url);
-        delegate = new HttpUrlConnectionDelegate(url, port);
-    }
-
-    protected HttpsURLConnectionImpl(URL url, int port, Proxy proxy) {
-        super(url);
-        delegate = new HttpUrlConnectionDelegate(url, port, proxy);
-    }
-
-    private void checkConnected() {
-        if (delegate.getSSLSocket() == null) {
-            throw new IllegalStateException("Connection has not yet been established");
-        }
-    }
-
-    HttpEngine getHttpEngine() {
-        return delegate.getHttpEngine();
-    }
-
-    @Override
-    public String getCipherSuite() {
-        SecureCacheResponse cacheResponse = delegate.getCacheResponse();
-        if (cacheResponse != null) {
-            return cacheResponse.getCipherSuite();
-        }
-        checkConnected();
-        return delegate.getSSLSocket().getSession().getCipherSuite();
-    }
-
-    @Override
-    public Certificate[] getLocalCertificates() {
-        SecureCacheResponse cacheResponse = delegate.getCacheResponse();
-        if (cacheResponse != null) {
-            List<Certificate> result = cacheResponse.getLocalCertificateChain();
-            return result != null ? result.toArray(new Certificate[result.size()]) : null;
-        }
-        checkConnected();
-        return delegate.getSSLSocket().getSession().getLocalCertificates();
-    }
-
-    @Override
-    public Certificate[] getServerCertificates() throws SSLPeerUnverifiedException {
-        SecureCacheResponse cacheResponse = delegate.getCacheResponse();
-        if (cacheResponse != null) {
-            List<Certificate> result = cacheResponse.getServerCertificateChain();
-            return result != null ? result.toArray(new Certificate[result.size()]) : null;
-        }
-        checkConnected();
-        return delegate.getSSLSocket().getSession().getPeerCertificates();
-    }
-
-    @Override
-    public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
-        SecureCacheResponse cacheResponse = delegate.getCacheResponse();
-        if (cacheResponse != null) {
-            return cacheResponse.getPeerPrincipal();
-        }
-        checkConnected();
-        return delegate.getSSLSocket().getSession().getPeerPrincipal();
-    }
-
-    @Override
-    public Principal getLocalPrincipal() {
-        SecureCacheResponse cacheResponse = delegate.getCacheResponse();
-        if (cacheResponse != null) {
-            return cacheResponse.getLocalPrincipal();
-        }
-        checkConnected();
-        return delegate.getSSLSocket().getSession().getLocalPrincipal();
-    }
-
-    @Override
-    public void disconnect() {
-        delegate.disconnect();
-    }
-
-    @Override
-    public InputStream getErrorStream() {
-        return delegate.getErrorStream();
-    }
-
-    @Override
-    public String getRequestMethod() {
-        return delegate.getRequestMethod();
-    }
-
-    @Override
-    public int getResponseCode() throws IOException {
-        return delegate.getResponseCode();
-    }
-
-    @Override
-    public String getResponseMessage() throws IOException {
-        return delegate.getResponseMessage();
-    }
-
-    @Override
-    public void setRequestMethod(String method) throws ProtocolException {
-        delegate.setRequestMethod(method);
-    }
-
-    @Override
-    public boolean usingProxy() {
-        return delegate.usingProxy();
-    }
-
-    @Override
-    public boolean getInstanceFollowRedirects() {
-        return delegate.getInstanceFollowRedirects();
-    }
-
-    @Override
-    public void setInstanceFollowRedirects(boolean followRedirects) {
-        delegate.setInstanceFollowRedirects(followRedirects);
-    }
-
-    @Override
-    public void connect() throws IOException {
-        connected = true;
-        delegate.connect();
-    }
-
-    @Override
-    public boolean getAllowUserInteraction() {
-        return delegate.getAllowUserInteraction();
-    }
-
-    @Override
-    public Object getContent() throws IOException {
-        return delegate.getContent();
-    }
-
-    @SuppressWarnings("unchecked") // Spec does not generify
-    @Override
-    public Object getContent(Class[] types) throws IOException {
-        return delegate.getContent(types);
-    }
-
-    @Override
-    public String getContentEncoding() {
-        return delegate.getContentEncoding();
-    }
-
-    @Override
-    public int getContentLength() {
-        return delegate.getContentLength();
-    }
-
-    @Override
-    public String getContentType() {
-        return delegate.getContentType();
-    }
-
-    @Override
-    public long getDate() {
-        return delegate.getDate();
-    }
-
-    @Override
-    public boolean getDefaultUseCaches() {
-        return delegate.getDefaultUseCaches();
-    }
-
-    @Override
-    public boolean getDoInput() {
-        return delegate.getDoInput();
-    }
-
-    @Override
-    public boolean getDoOutput() {
-        return delegate.getDoOutput();
-    }
-
-    @Override
-    public long getExpiration() {
-        return delegate.getExpiration();
-    }
-
-    @Override
-    public String getHeaderField(int pos) {
-        return delegate.getHeaderField(pos);
-    }
-
-    @Override
-    public Map<String, List<String>> getHeaderFields() {
-        return delegate.getHeaderFields();
-    }
-
-    @Override
-    public Map<String, List<String>> getRequestProperties() {
-        return delegate.getRequestProperties();
-    }
-
-    @Override
-    public void addRequestProperty(String field, String newValue) {
-        delegate.addRequestProperty(field, newValue);
-    }
-
-    @Override
-    public String getHeaderField(String key) {
-        return delegate.getHeaderField(key);
-    }
-
-    @Override
-    public long getHeaderFieldDate(String field, long defaultValue) {
-        return delegate.getHeaderFieldDate(field, defaultValue);
-    }
-
-    @Override
-    public int getHeaderFieldInt(String field, int defaultValue) {
-        return delegate.getHeaderFieldInt(field, defaultValue);
-    }
-
-    @Override
-    public String getHeaderFieldKey(int posn) {
-        return delegate.getHeaderFieldKey(posn);
-    }
-
-    @Override
-    public long getIfModifiedSince() {
-        return delegate.getIfModifiedSince();
-    }
-
-    @Override
-    public InputStream getInputStream() throws IOException {
-        return delegate.getInputStream();
-    }
-
-    @Override
-    public long getLastModified() {
-        return delegate.getLastModified();
-    }
-
-    @Override
-    public OutputStream getOutputStream() throws IOException {
-        return delegate.getOutputStream();
-    }
-
-    @Override
-    public Permission getPermission() throws IOException {
-        return delegate.getPermission();
-    }
-
-    @Override
-    public String getRequestProperty(String field) {
-        return delegate.getRequestProperty(field);
-    }
-
-    @Override
-    public URL getURL() {
-        return delegate.getURL();
-    }
-
-    @Override
-    public boolean getUseCaches() {
-        return delegate.getUseCaches();
-    }
-
-    @Override
-    public void setAllowUserInteraction(boolean newValue) {
-        delegate.setAllowUserInteraction(newValue);
-    }
-
-    @Override
-    public void setDefaultUseCaches(boolean newValue) {
-        delegate.setDefaultUseCaches(newValue);
-    }
-
-    @Override
-    public void setDoInput(boolean newValue) {
-        delegate.setDoInput(newValue);
-    }
-
-    @Override
-    public void setDoOutput(boolean newValue) {
-        delegate.setDoOutput(newValue);
-    }
-
-    @Override
-    public void setIfModifiedSince(long newValue) {
-        delegate.setIfModifiedSince(newValue);
-    }
-
-    @Override
-    public void setRequestProperty(String field, String newValue) {
-        delegate.setRequestProperty(field, newValue);
-    }
-
-    @Override
-    public void setUseCaches(boolean newValue) {
-        delegate.setUseCaches(newValue);
-    }
-
-    @Override
-    public void setConnectTimeout(int timeoutMillis) {
-        delegate.setConnectTimeout(timeoutMillis);
-    }
-
-    @Override
-    public int getConnectTimeout() {
-        return delegate.getConnectTimeout();
-    }
-
-    @Override
-    public void setReadTimeout(int timeoutMillis) {
-        delegate.setReadTimeout(timeoutMillis);
-    }
-
-    @Override
-    public int getReadTimeout() {
-        return delegate.getReadTimeout();
-    }
-
-    @Override
-    public String toString() {
-        return delegate.toString();
-    }
-
-    @Override
-    public void setFixedLengthStreamingMode(int contentLength) {
-        delegate.setFixedLengthStreamingMode(contentLength);
-    }
-
-    @Override
-    public void setChunkedStreamingMode(int chunkLength) {
-        delegate.setChunkedStreamingMode(chunkLength);
-    }
-
-    private final class HttpUrlConnectionDelegate extends HttpURLConnectionImpl {
-        private HttpUrlConnectionDelegate(URL url, int port) {
-            super(url, port);
-        }
-
-        private HttpUrlConnectionDelegate(URL url, int port, Proxy proxy) {
-            super(url, port, proxy);
-        }
-
-        @Override protected HttpEngine newHttpEngine(String method, RawHeaders requestHeaders,
-                HttpConnection connection, RetryableOutputStream requestBody) throws IOException {
-            return new HttpsEngine(this, method, requestHeaders, connection, requestBody,
-                    HttpsURLConnectionImpl.this);
-        }
-
-        public SecureCacheResponse getCacheResponse() {
-            HttpsEngine engine = (HttpsEngine) httpEngine;
-            return engine != null ? (SecureCacheResponse) engine.getCacheResponse() : null;
-        }
-
-        public SSLSocket getSSLSocket() {
-            HttpsEngine engine = (HttpsEngine) httpEngine;
-            return engine != null ? engine.sslSocket : null;
-        }
-    }
-
-    private static class HttpsEngine extends HttpEngine {
-
-        /**
-         * Local stash of HttpsEngine.connection.sslSocket for answering
-         * queries such as getCipherSuite even after
-         * httpsEngine.Connection has been recycled. It's presence is also
-         * used to tell if the HttpsURLConnection is considered connected,
-         * as opposed to the connected field of URLConnection or the a
-         * non-null connect in HttpURLConnectionImpl
-         */
-        private SSLSocket sslSocket;
-
-        private final HttpsURLConnectionImpl enclosing;
-
-        /**
-         * @param policy the HttpURLConnectionImpl with connection configuration
-         * @param enclosing the HttpsURLConnection with HTTPS features
-         */
-        private HttpsEngine(HttpURLConnectionImpl policy, String method, RawHeaders requestHeaders,
-                HttpConnection connection, RetryableOutputStream requestBody,
-                HttpsURLConnectionImpl enclosing) throws IOException {
-            super(policy, method, requestHeaders, connection, requestBody);
-            this.sslSocket = connection != null ? connection.getSecureSocketIfConnected() : null;
-            this.enclosing = enclosing;
-        }
-
-        @Override protected void connect() throws IOException {
-            // first try an SSL connection with compression and
-            // various TLS extensions enabled, if it fails (and its
-            // not unheard of that it will) fallback to a more
-            // barebones connections
-            boolean connectionReused;
-            try {
-                connectionReused = makeSslConnection(true);
-            } catch (IOException e) {
-                // If the problem was a CertificateException from the X509TrustManager,
-                // do not retry, we didn't have an abrupt server initiated exception.
-                if (e instanceof SSLHandshakeException
-                        && e.getCause() instanceof CertificateException) {
-                    throw e;
-                }
-                release(false);
-                connectionReused = makeSslConnection(false);
-            }
-
-            if (!connectionReused) {
-                sslSocket = connection.verifySecureSocketHostname(enclosing.getHostnameVerifier());
-            }
-        }
-
-        /**
-         * Attempt to make an https connection. Returns true if a
-         * connection was reused, false otherwise.
-         *
-         * @param tlsTolerant If true, assume server can handle common
-         * TLS extensions and SSL deflate compression. If false, use
-         * an SSL3 only fallback mode without compression.
-         */
-        private boolean makeSslConnection(boolean tlsTolerant) throws IOException {
-            // make an SSL Tunnel on the first message pair of each SSL + proxy connection
-            if (connection == null) {
-                connection = openSocketConnection();
-                if (connection.getAddress().getProxy() != null) {
-                    makeTunnel(policy, connection, getRequestHeaders());
-                }
-            }
-
-            // if super.makeConnection returned a connection from the
-            // pool, sslSocket needs to be initialized here. If it is
-            // a new connection, it will be initialized by
-            // getSecureSocket below.
-            sslSocket = connection.getSecureSocketIfConnected();
-
-            // we already have an SSL connection,
-            if (sslSocket != null) {
-                return true;
-            }
-
-            connection.setupSecureSocket(enclosing.getSSLSocketFactory(), tlsTolerant);
-            return false;
-        }
-
-        /**
-         * To make an HTTPS connection over an HTTP proxy, send an unencrypted
-         * CONNECT request to create the proxy connection. This may need to be
-         * retried if the proxy requires authorization.
-         */
-        private void makeTunnel(HttpURLConnectionImpl policy, HttpConnection connection,
-                RequestHeaders requestHeaders) throws IOException {
-            RawHeaders rawRequestHeaders = requestHeaders.getHeaders();
-            while (true) {
-                HttpEngine connect = new ProxyConnectEngine(policy, rawRequestHeaders, connection);
-                connect.sendRequest();
-                connect.readResponse();
-
-                int responseCode = connect.getResponseCode();
-                switch (connect.getResponseCode()) {
-                case HTTP_OK:
-                    return;
-                case HTTP_PROXY_AUTH:
-                    rawRequestHeaders = new RawHeaders(rawRequestHeaders);
-                    boolean credentialsFound = policy.processAuthHeader(HTTP_PROXY_AUTH,
-                            connect.getResponseHeaders(), rawRequestHeaders);
-                    if (credentialsFound) {
-                        continue;
-                    } else {
-                        throw new IOException("Failed to authenticate with proxy");
-                    }
-                default:
-                    throw new IOException("Unexpected response code for CONNECT: " + responseCode);
-                }
-            }
-        }
-
-        @Override protected boolean acceptCacheResponseType(CacheResponse cacheResponse) {
-            return cacheResponse instanceof SecureCacheResponse;
-        }
-
-        @Override protected boolean includeAuthorityInRequestLine() {
-            // Even if there is a proxy, it isn't involved. Always request just the file.
-            return false;
-        }
-
-        @Override protected SSLSocketFactory getSslSocketFactory() {
-            return enclosing.getSSLSocketFactory();
-        }
-
-        @Override protected HttpURLConnection getHttpConnectionToCache() {
-            return enclosing;
-        }
-    }
-
-    private static class ProxyConnectEngine extends HttpEngine {
-        public ProxyConnectEngine(HttpURLConnectionImpl policy, RawHeaders requestHeaders,
-                HttpConnection connection) throws IOException {
-            super(policy, HttpEngine.CONNECT, requestHeaders, connection, null);
-        }
-
-        /**
-         * If we're establishing an HTTPS tunnel with CONNECT (RFC 2817 5.2), send
-         * only the minimum set of headers. This avoids sending potentially
-         * sensitive data like HTTP cookies to the proxy unencrypted.
-         */
-        @Override protected RawHeaders getNetworkRequestHeaders() throws IOException {
-            RequestHeaders privateHeaders = getRequestHeaders();
-            URL url = policy.getURL();
-
-            RawHeaders result = new RawHeaders();
-            result.setStatusLine("CONNECT " + url.getHost() + ":" + url.getEffectivePort()
-                    + " HTTP/1.1");
-
-            // Always set Host and User-Agent.
-            String host = privateHeaders.getHost();
-            if (host == null) {
-                host = getOriginAddress(url);
-            }
-            result.set("Host", host);
-
-            String userAgent = privateHeaders.getUserAgent();
-            if (userAgent == null) {
-                userAgent = getDefaultUserAgent();
-            }
-            result.set("User-Agent", userAgent);
-
-            // Copy over the Proxy-Authorization header if it exists.
-            String proxyAuthorization = privateHeaders.getProxyAuthorization();
-            if (proxyAuthorization != null) {
-                result.set("Proxy-Authorization", proxyAuthorization);
-            }
-
-            // Always set the Proxy-Connection to Keep-Alive for the benefit of
-            // HTTP/1.0 proxies like Squid.
-            result.set("Proxy-Connection", "Keep-Alive");
-            return result;
-        }
-
-        @Override protected boolean requiresTunnel() {
-            return true;
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/RawHeaders.java b/luni/src/main/java/libcore/net/http/RawHeaders.java
deleted file mode 100644
index 21b48f1..0000000
--- a/luni/src/main/java/libcore/net/http/RawHeaders.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-
-/**
- * The HTTP status and unparsed header fields of a single HTTP message. Values
- * are represented as uninterpreted strings; use {@link RequestHeaders} and
- * {@link ResponseHeaders} for interpreted headers. This class maintains the
- * order of the header fields within the HTTP message.
- *
- * <p>This class tracks fields line-by-line. A field with multiple comma-
- * separated values on the same line will be treated as a field with a single
- * value by this class. It is the caller's responsibility to detect and split
- * on commas if their field permits multiple values. This simplifies use of
- * single-valued fields whose values routinely contain commas, such as cookies
- * or dates.
- *
- * <p>This class trims whitespace from values. It never returns values with
- * leading or trailing whitespace.
- */
-public final class RawHeaders {
-    private static final Comparator<String> FIELD_NAME_COMPARATOR = new Comparator<String>() {
-        @FindBugsSuppressWarnings("ES_COMPARING_PARAMETER_STRING_WITH_EQ")
-        @Override public int compare(String a, String b) {
-            if (a == b) {
-                return 0;
-            } else if (a == null) {
-                return -1;
-            } else if (b == null) {
-                return 1;
-            } else {
-                return String.CASE_INSENSITIVE_ORDER.compare(a, b);
-            }
-        }
-    };
-
-    private final List<String> namesAndValues = new ArrayList<String>(20);
-    private String statusLine;
-    private int httpMinorVersion = 1;
-    private int responseCode = -1;
-    private String responseMessage;
-
-    public RawHeaders() {}
-
-    public RawHeaders(RawHeaders copyFrom) {
-        namesAndValues.addAll(copyFrom.namesAndValues);
-        statusLine = copyFrom.statusLine;
-        httpMinorVersion = copyFrom.httpMinorVersion;
-        responseCode = copyFrom.responseCode;
-        responseMessage = copyFrom.responseMessage;
-    }
-
-    /**
-     * Sets the response status line (like "HTTP/1.0 200 OK") or request line
-     * (like "GET / HTTP/1.1").
-     */
-    public void setStatusLine(String statusLine) {
-        statusLine = statusLine.trim();
-        this.statusLine = statusLine;
-
-        if (statusLine == null || !statusLine.startsWith("HTTP/")) {
-            return;
-        }
-        statusLine = statusLine.trim();
-        int mark = statusLine.indexOf(" ") + 1;
-        if (mark == 0) {
-            return;
-        }
-        if (statusLine.charAt(mark - 2) != '1') {
-            this.httpMinorVersion = 0;
-        }
-        int last = mark + 3;
-        if (last > statusLine.length()) {
-            last = statusLine.length();
-        }
-        this.responseCode = Integer.parseInt(statusLine.substring(mark, last));
-        if (last + 1 <= statusLine.length()) {
-            this.responseMessage = statusLine.substring(last + 1);
-        }
-    }
-
-    public String getStatusLine() {
-        return statusLine;
-    }
-
-    /**
-     * Returns the status line's HTTP minor version. This returns 0 for HTTP/1.0
-     * and 1 for HTTP/1.1. This returns 1 if the HTTP version is unknown.
-     */
-    public int getHttpMinorVersion() {
-        return httpMinorVersion != -1 ? httpMinorVersion : 1;
-    }
-
-    /**
-     * Returns the HTTP status code or -1 if it is unknown.
-     */
-    public int getResponseCode() {
-        return responseCode;
-    }
-
-    /**
-     * Returns the HTTP status message or null if it is unknown.
-     */
-    public String getResponseMessage() {
-        return responseMessage;
-    }
-
-    /**
-     * Add an HTTP header line containing a field name, a literal colon, and a
-     * value.
-     */
-    public void addLine(String line) {
-        int index = line.indexOf(":");
-        if (index == -1) {
-            add("", line);
-        } else {
-            add(line.substring(0, index), line.substring(index + 1));
-        }
-    }
-
-    /**
-     * Add a field with the specified value.
-     */
-    public void add(String fieldName, String value) {
-        if (fieldName == null) {
-            throw new IllegalArgumentException("fieldName == null");
-        }
-        if (value == null) {
-            /*
-             * Given null values, the RI sends a malformed field line like
-             * "Accept\r\n". For platform compatibility and HTTP compliance, we
-             * print a warning and ignore null values.
-             */
-            System.logW("Ignoring HTTP header field '" + fieldName + "' because its value is null");
-            return;
-        }
-        namesAndValues.add(fieldName);
-        namesAndValues.add(value.trim());
-    }
-
-    public void removeAll(String fieldName) {
-        for (int i = 0; i < namesAndValues.size(); i += 2) {
-            if (fieldName.equalsIgnoreCase(namesAndValues.get(i))) {
-                namesAndValues.remove(i); // field name
-                namesAndValues.remove(i); // value
-            }
-        }
-    }
-
-    public void addAll(String fieldName, List<String> headerFields) {
-        for (String value : headerFields) {
-            add(fieldName, value);
-        }
-    }
-
-    /**
-     * Set a field with the specified value. If the field is not found, it is
-     * added. If the field is found, the existing values are replaced.
-     */
-    public void set(String fieldName, String value) {
-        removeAll(fieldName);
-        add(fieldName, value);
-    }
-
-    /**
-     * Returns the number of field values.
-     */
-    public int length() {
-        return namesAndValues.size() / 2;
-    }
-
-    /**
-     * Returns the field at {@code position} or null if that is out of range.
-     */
-    public String getFieldName(int index) {
-        int fieldNameIndex = index * 2;
-        if (fieldNameIndex < 0 || fieldNameIndex >= namesAndValues.size()) {
-            return null;
-        }
-        return namesAndValues.get(fieldNameIndex);
-    }
-
-    /**
-     * Returns the value at {@code index} or null if that is out of range.
-     */
-    public String getValue(int index) {
-        int valueIndex = index * 2 + 1;
-        if (valueIndex < 0 || valueIndex >= namesAndValues.size()) {
-            return null;
-        }
-        return namesAndValues.get(valueIndex);
-    }
-
-    /**
-     * Returns the last value corresponding to the specified field, or null.
-     */
-    public String get(String fieldName) {
-        for (int i = namesAndValues.size() - 2; i >= 0; i -= 2) {
-            if (fieldName.equalsIgnoreCase(namesAndValues.get(i))) {
-                return namesAndValues.get(i + 1);
-            }
-        }
-        return null;
-    }
-
-    /**
-     * @param fieldNames a case-insensitive set of HTTP header field names.
-     */
-    public RawHeaders getAll(Set<String> fieldNames) {
-        RawHeaders result = new RawHeaders();
-        for (int i = 0; i < namesAndValues.size(); i += 2) {
-            String fieldName = namesAndValues.get(i);
-            if (fieldNames.contains(fieldName)) {
-                result.add(fieldName, namesAndValues.get(i + 1));
-            }
-        }
-        return result;
-    }
-
-    public String toHeaderString() {
-        StringBuilder result = new StringBuilder(256);
-        result.append(statusLine).append("\r\n");
-        for (int i = 0; i < namesAndValues.size(); i += 2) {
-            result.append(namesAndValues.get(i)).append(": ")
-                    .append(namesAndValues.get(i + 1)).append("\r\n");
-        }
-        result.append("\r\n");
-        return result.toString();
-    }
-
-    /**
-     * Returns an immutable map containing each field to its list of values. The
-     * status line is mapped to null.
-     */
-    public Map<String, List<String>> toMultimap() {
-        Map<String, List<String>> result = new TreeMap<String, List<String>>(FIELD_NAME_COMPARATOR);
-        for (int i = 0; i < namesAndValues.size(); i += 2) {
-            String fieldName = namesAndValues.get(i);
-            String value = namesAndValues.get(i + 1);
-
-            List<String> allValues = new ArrayList<String>();
-            List<String> otherValues = result.get(fieldName);
-            if (otherValues != null) {
-                allValues.addAll(otherValues);
-            }
-            allValues.add(value);
-            result.put(fieldName, Collections.unmodifiableList(allValues));
-        }
-        if (statusLine != null) {
-            result.put(null, Collections.unmodifiableList(Collections.singletonList(statusLine)));
-        }
-        return Collections.unmodifiableMap(result);
-    }
-
-    /**
-     * Creates a new instance from the given map of fields to values. If
-     * present, the null field's last element will be used to set the status
-     * line.
-     */
-    public static RawHeaders fromMultimap(Map<String, List<String>> map) {
-        RawHeaders result = new RawHeaders();
-        for (Entry<String, List<String>> entry : map.entrySet()) {
-            String fieldName = entry.getKey();
-            List<String> values = entry.getValue();
-            if (fieldName != null) {
-                result.addAll(fieldName, values);
-            } else if (!values.isEmpty()) {
-                result.setStatusLine(values.get(values.size() - 1));
-            }
-        }
-        return result;
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/RequestHeaders.java b/luni/src/main/java/libcore/net/http/RequestHeaders.java
deleted file mode 100644
index 3b536ce..0000000
--- a/luni/src/main/java/libcore/net/http/RequestHeaders.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.net.URI;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Parsed HTTP request headers.
- */
-public final class RequestHeaders {
-    private final URI uri;
-    private final RawHeaders headers;
-
-    /** Don't use a cache to satisfy this request. */
-    private boolean noCache;
-    private int maxAgeSeconds = -1;
-    private int maxStaleSeconds = -1;
-    private int minFreshSeconds = -1;
-
-    /**
-     * This field's name "only-if-cached" is misleading. It actually means "do
-     * not use the network". It is set by a client who only wants to make a
-     * request if it can be fully satisfied by the cache. Cached responses that
-     * would require validation (ie. conditional gets) are not permitted if this
-     * header is set.
-     */
-    private boolean onlyIfCached;
-
-    /**
-     * True if the request contains an authorization field. Although this isn't
-     * necessarily a shared cache, it follows the spec's strict requirements for
-     * shared caches.
-     */
-    private boolean hasAuthorization;
-
-    private int contentLength = -1;
-    private String transferEncoding;
-    private String userAgent;
-    private String host;
-    private String connection;
-    private String acceptEncoding;
-    private String contentType;
-    private String ifModifiedSince;
-    private String ifNoneMatch;
-    private String proxyAuthorization;
-
-    public RequestHeaders(URI uri, RawHeaders headers) {
-        this.uri = uri;
-        this.headers = headers;
-
-        HeaderParser.CacheControlHandler handler = new HeaderParser.CacheControlHandler() {
-            @Override public void handle(String directive, String parameter) {
-                if (directive.equalsIgnoreCase("no-cache")) {
-                    noCache = true;
-                } else if (directive.equalsIgnoreCase("max-age")) {
-                    maxAgeSeconds = HeaderParser.parseSeconds(parameter);
-                } else if (directive.equalsIgnoreCase("max-stale")) {
-                    maxStaleSeconds = HeaderParser.parseSeconds(parameter);
-                } else if (directive.equalsIgnoreCase("min-fresh")) {
-                    minFreshSeconds = HeaderParser.parseSeconds(parameter);
-                } else if (directive.equalsIgnoreCase("only-if-cached")) {
-                    onlyIfCached = true;
-                }
-            }
-        };
-
-        for (int i = 0; i < headers.length(); i++) {
-            String fieldName = headers.getFieldName(i);
-            String value = headers.getValue(i);
-            if ("Cache-Control".equalsIgnoreCase(fieldName)) {
-                HeaderParser.parseCacheControl(value, handler);
-            } else if ("Pragma".equalsIgnoreCase(fieldName)) {
-                if (value.equalsIgnoreCase("no-cache")) {
-                    noCache = true;
-                }
-            } else if ("If-None-Match".equalsIgnoreCase(fieldName)) {
-                ifNoneMatch = value;
-            } else if ("If-Modified-Since".equalsIgnoreCase(fieldName)) {
-                ifModifiedSince = value;
-            } else if ("Authorization".equalsIgnoreCase(fieldName)) {
-                hasAuthorization = true;
-            } else if ("Content-Length".equalsIgnoreCase(fieldName)) {
-                try {
-                    contentLength = Integer.parseInt(value);
-                } catch (NumberFormatException ignored) {
-                }
-            } else if ("Transfer-Encoding".equalsIgnoreCase(fieldName)) {
-                transferEncoding = value;
-            } else if ("User-Agent".equalsIgnoreCase(fieldName)) {
-                userAgent = value;
-            } else if ("Host".equalsIgnoreCase(fieldName)) {
-                host = value;
-            } else if ("Connection".equalsIgnoreCase(fieldName)) {
-                connection = value;
-            } else if ("Accept-Encoding".equalsIgnoreCase(fieldName)) {
-                acceptEncoding = value;
-            } else if ("Content-Type".equalsIgnoreCase(fieldName)) {
-                contentType = value;
-            } else if ("Proxy-Authorization".equalsIgnoreCase(fieldName)) {
-                proxyAuthorization = value;
-            }
-        }
-    }
-
-    public boolean isChunked() {
-        return "chunked".equalsIgnoreCase(transferEncoding);
-    }
-
-    public boolean hasConnectionClose() {
-        return "close".equalsIgnoreCase(connection);
-    }
-
-    public URI getUri() {
-        return uri;
-    }
-
-    public RawHeaders getHeaders() {
-        return headers;
-    }
-
-    public boolean isNoCache() {
-        return noCache;
-    }
-
-    public int getMaxAgeSeconds() {
-        return maxAgeSeconds;
-    }
-
-    public int getMaxStaleSeconds() {
-        return maxStaleSeconds;
-    }
-
-    public int getMinFreshSeconds() {
-        return minFreshSeconds;
-    }
-
-    public boolean isOnlyIfCached() {
-        return onlyIfCached;
-    }
-
-    public boolean hasAuthorization() {
-        return hasAuthorization;
-    }
-
-    public int getContentLength() {
-        return contentLength;
-    }
-
-    public String getTransferEncoding() {
-        return transferEncoding;
-    }
-
-    public String getUserAgent() {
-        return userAgent;
-    }
-
-    public String getHost() {
-        return host;
-    }
-
-    public String getConnection() {
-        return connection;
-    }
-
-    public String getAcceptEncoding() {
-        return acceptEncoding;
-    }
-
-    public String getContentType() {
-        return contentType;
-    }
-
-    public String getIfModifiedSince() {
-        return ifModifiedSince;
-    }
-
-    public String getIfNoneMatch() {
-        return ifNoneMatch;
-    }
-
-    public String getProxyAuthorization() {
-        return proxyAuthorization;
-    }
-
-    public void setChunked() {
-        if (this.transferEncoding != null) {
-            headers.removeAll("Transfer-Encoding");
-        }
-        headers.add("Transfer-Encoding", "chunked");
-        this.transferEncoding = "chunked";
-    }
-
-    public void setContentLength(int contentLength) {
-        if (this.contentLength != -1) {
-            headers.removeAll("Content-Length");
-        }
-        headers.add("Content-Length", Integer.toString(contentLength));
-        this.contentLength = contentLength;
-    }
-
-    public void setUserAgent(String userAgent) {
-        if (this.userAgent != null) {
-            headers.removeAll("User-Agent");
-        }
-        headers.add("User-Agent", userAgent);
-        this.userAgent = userAgent;
-    }
-
-    public void setHost(String host) {
-        if (this.host != null) {
-            headers.removeAll("Host");
-        }
-        headers.add("Host", host);
-        this.host = host;
-    }
-
-    public void setConnection(String connection) {
-        if (this.connection != null) {
-            headers.removeAll("Connection");
-        }
-        headers.add("Connection", connection);
-        this.connection = connection;
-    }
-
-    public void setAcceptEncoding(String acceptEncoding) {
-        if (this.acceptEncoding != null) {
-            headers.removeAll("Accept-Encoding");
-        }
-        headers.add("Accept-Encoding", acceptEncoding);
-        this.acceptEncoding = acceptEncoding;
-    }
-
-    public void setContentType(String contentType) {
-        if (this.contentType != null) {
-            headers.removeAll("Content-Type");
-        }
-        headers.add("Content-Type", contentType);
-        this.contentType = contentType;
-    }
-
-    public void setIfModifiedSince(Date date) {
-        if (ifModifiedSince != null) {
-            headers.removeAll("If-Modified-Since");
-        }
-        String formattedDate = HttpDate.format(date);
-        headers.add("If-Modified-Since", formattedDate);
-        ifModifiedSince = formattedDate;
-    }
-
-    public void setIfNoneMatch(String ifNoneMatch) {
-        if (this.ifNoneMatch != null) {
-            headers.removeAll("If-None-Match");
-        }
-        headers.add("If-None-Match", ifNoneMatch);
-        this.ifNoneMatch = ifNoneMatch;
-    }
-
-    /**
-     * Returns true if the request contains conditions that save the server from
-     * sending a response that the client has locally. When the caller adds
-     * conditions, this cache won't participate in the request.
-     */
-    public boolean hasConditions() {
-        return ifModifiedSince != null || ifNoneMatch != null;
-    }
-
-    public void addCookies(Map<String, List<String>> allCookieHeaders) {
-        for (Map.Entry<String, List<String>> entry : allCookieHeaders.entrySet()) {
-            String key = entry.getKey();
-            if ("Cookie".equalsIgnoreCase(key) || "Cookie2".equalsIgnoreCase(key)) {
-                headers.addAll(key, entry.getValue());
-            }
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/ResponseHeaders.java b/luni/src/main/java/libcore/net/http/ResponseHeaders.java
deleted file mode 100644
index c0b4200..0000000
--- a/luni/src/main/java/libcore/net/http/ResponseHeaders.java
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.net.HttpURLConnection;
-import java.net.ResponseSource;
-import java.net.URI;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.TimeUnit;
-import libcore.util.Objects;
-
-/**
- * Parsed HTTP response headers.
- */
-public final class ResponseHeaders {
-
-    /** HTTP header name for the local time when the request was sent. */
-    private static final String SENT_MILLIS = "X-Android-Sent-Millis";
-
-    /** HTTP header name for the local time when the response was received. */
-    private static final String RECEIVED_MILLIS = "X-Android-Received-Millis";
-
-    private final URI uri;
-    private final RawHeaders headers;
-
-    /** The server's time when this response was served, if known. */
-    private Date servedDate;
-
-    /** The last modified date of the response, if known. */
-    private Date lastModified;
-
-    /**
-     * The expiration date of the response, if known. If both this field and the
-     * max age are set, the max age is preferred.
-     */
-    private Date expires;
-
-    /**
-     * Extension header set by HttpURLConnectionImpl specifying the timestamp
-     * when the HTTP request was first initiated.
-     */
-    private long sentRequestMillis;
-
-    /**
-     * Extension header set by HttpURLConnectionImpl specifying the timestamp
-     * when the HTTP response was first received.
-     */
-    private long receivedResponseMillis;
-
-    /**
-     * In the response, this field's name "no-cache" is misleading. It doesn't
-     * prevent us from caching the response; it only means we have to validate
-     * the response with the origin server before returning it. We can do this
-     * with a conditional get.
-     */
-    private boolean noCache;
-
-    /** If true, this response should not be cached. */
-    private boolean noStore;
-
-    /**
-     * The duration past the response's served date that it can be served
-     * without validation.
-     */
-    private int maxAgeSeconds = -1;
-
-    /**
-     * The "s-maxage" directive is the max age for shared caches. Not to be
-     * confused with "max-age" for non-shared caches, As in Firefox and Chrome,
-     * this directive is not honored by this cache.
-     */
-    private int sMaxAgeSeconds = -1;
-
-    /**
-     * This request header field's name "only-if-cached" is misleading. It
-     * actually means "do not use the network". It is set by a client who only
-     * wants to make a request if it can be fully satisfied by the cache.
-     * Cached responses that would require validation (ie. conditional gets) are
-     * not permitted if this header is set.
-     */
-    private boolean isPublic;
-    private boolean mustRevalidate;
-    private String etag;
-    private int ageSeconds = -1;
-
-    /** Case-insensitive set of field names. */
-    private Set<String> varyFields = Collections.emptySet();
-
-    private String contentEncoding;
-    private String transferEncoding;
-    private int contentLength = -1;
-    private String connection;
-
-    public ResponseHeaders(URI uri, RawHeaders headers) {
-        this.uri = uri;
-        this.headers = headers;
-
-        HeaderParser.CacheControlHandler handler = new HeaderParser.CacheControlHandler() {
-            @Override public void handle(String directive, String parameter) {
-                if (directive.equalsIgnoreCase("no-cache")) {
-                    noCache = true;
-                } else if (directive.equalsIgnoreCase("no-store")) {
-                    noStore = true;
-                } else if (directive.equalsIgnoreCase("max-age")) {
-                    maxAgeSeconds = HeaderParser.parseSeconds(parameter);
-                } else if (directive.equalsIgnoreCase("s-maxage")) {
-                    sMaxAgeSeconds = HeaderParser.parseSeconds(parameter);
-                } else if (directive.equalsIgnoreCase("public")) {
-                    isPublic = true;
-                } else if (directive.equalsIgnoreCase("must-revalidate")) {
-                    mustRevalidate = true;
-                }
-            }
-        };
-
-        for (int i = 0; i < headers.length(); i++) {
-            String fieldName = headers.getFieldName(i);
-            String value = headers.getValue(i);
-            if ("Cache-Control".equalsIgnoreCase(fieldName)) {
-                HeaderParser.parseCacheControl(value, handler);
-            } else if ("Date".equalsIgnoreCase(fieldName)) {
-                servedDate = HttpDate.parse(value);
-            } else if ("Expires".equalsIgnoreCase(fieldName)) {
-                expires = HttpDate.parse(value);
-            } else if ("Last-Modified".equalsIgnoreCase(fieldName)) {
-                lastModified = HttpDate.parse(value);
-            } else if ("ETag".equalsIgnoreCase(fieldName)) {
-                etag = value;
-            } else if ("Pragma".equalsIgnoreCase(fieldName)) {
-                if (value.equalsIgnoreCase("no-cache")) {
-                    noCache = true;
-                }
-            } else if ("Age".equalsIgnoreCase(fieldName)) {
-                ageSeconds = HeaderParser.parseSeconds(value);
-            } else if ("Vary".equalsIgnoreCase(fieldName)) {
-                // Replace the immutable empty set with something we can mutate.
-                if (varyFields.isEmpty()) {
-                    varyFields = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
-                }
-                for (String varyField : value.split(",")) {
-                    varyFields.add(varyField.trim());
-                }
-            } else if ("Content-Encoding".equalsIgnoreCase(fieldName)) {
-                contentEncoding = value;
-            } else if ("Transfer-Encoding".equalsIgnoreCase(fieldName)) {
-                transferEncoding = value;
-            } else if ("Content-Length".equalsIgnoreCase(fieldName)) {
-                try {
-                    contentLength = Integer.parseInt(value);
-                } catch (NumberFormatException ignored) {
-                }
-            } else if ("Connection".equalsIgnoreCase(fieldName)) {
-                connection = value;
-            } else if (SENT_MILLIS.equalsIgnoreCase(fieldName)) {
-                sentRequestMillis = Long.parseLong(value);
-            } else if (RECEIVED_MILLIS.equalsIgnoreCase(fieldName)) {
-                receivedResponseMillis = Long.parseLong(value);
-            }
-        }
-    }
-
-    public boolean isContentEncodingGzip() {
-        return "gzip".equalsIgnoreCase(contentEncoding);
-    }
-
-    public void stripContentEncoding() {
-        contentEncoding = null;
-        headers.removeAll("Content-Encoding");
-    }
-
-    public void stripContentLength() {
-        contentLength = -1;
-        headers.removeAll("Content-Length");
-    }
-
-    public boolean isChunked() {
-        return "chunked".equalsIgnoreCase(transferEncoding);
-    }
-
-    public boolean hasConnectionClose() {
-        return "close".equalsIgnoreCase(connection);
-    }
-
-    public URI getUri() {
-        return uri;
-    }
-
-    public RawHeaders getHeaders() {
-        return headers;
-    }
-
-    public Date getServedDate() {
-        return servedDate;
-    }
-
-    public Date getLastModified() {
-        return lastModified;
-    }
-
-    public Date getExpires() {
-        return expires;
-    }
-
-    public boolean isNoCache() {
-        return noCache;
-    }
-
-    public boolean isNoStore() {
-        return noStore;
-    }
-
-    public int getMaxAgeSeconds() {
-        return maxAgeSeconds;
-    }
-
-    public int getSMaxAgeSeconds() {
-        return sMaxAgeSeconds;
-    }
-
-    public boolean isPublic() {
-        return isPublic;
-    }
-
-    public boolean isMustRevalidate() {
-        return mustRevalidate;
-    }
-
-    public String getEtag() {
-        return etag;
-    }
-
-    public Set<String> getVaryFields() {
-        return varyFields;
-    }
-
-    public String getContentEncoding() {
-        return contentEncoding;
-    }
-
-    public int getContentLength() {
-        return contentLength;
-    }
-
-    public String getConnection() {
-        return connection;
-    }
-
-    public void setLocalTimestamps(long sentRequestMillis, long receivedResponseMillis) {
-        this.sentRequestMillis = sentRequestMillis;
-        headers.add(SENT_MILLIS, Long.toString(sentRequestMillis));
-        this.receivedResponseMillis = receivedResponseMillis;
-        headers.add(RECEIVED_MILLIS, Long.toString(receivedResponseMillis));
-    }
-
-    /**
-     * Returns the current age of the response, in milliseconds. The calculation
-     * is specified by RFC 2616, 13.2.3 Age Calculations.
-     */
-    private long computeAge(long nowMillis) {
-        long apparentReceivedAge = servedDate != null
-                ? Math.max(0, receivedResponseMillis - servedDate.getTime())
-                : 0;
-        long receivedAge = ageSeconds != -1
-                ? Math.max(apparentReceivedAge, TimeUnit.SECONDS.toMillis(ageSeconds))
-                : apparentReceivedAge;
-        long responseDuration = receivedResponseMillis - sentRequestMillis;
-        long residentDuration = nowMillis - receivedResponseMillis;
-        return receivedAge + responseDuration + residentDuration;
-    }
-
-    /**
-     * Returns the number of milliseconds that the response was fresh for,
-     * starting from the served date.
-     */
-    private long computeFreshnessLifetime() {
-        if (maxAgeSeconds != -1) {
-            return TimeUnit.SECONDS.toMillis(maxAgeSeconds);
-        } else if (expires != null) {
-            long servedMillis = servedDate != null ? servedDate.getTime() : receivedResponseMillis;
-            long delta = expires.getTime() - servedMillis;
-            return delta > 0 ? delta : 0;
-        } else if (lastModified != null && uri.getRawQuery() == null) {
-            /*
-             * As recommended by the HTTP RFC and implemented in Firefox, the
-             * max age of a document should be defaulted to 10% of the
-             * document's age at the time it was served. Default expiration
-             * dates aren't used for URIs containing a query.
-             */
-            long servedMillis = servedDate != null ? servedDate.getTime() : sentRequestMillis;
-            long delta = servedMillis - lastModified.getTime();
-            return delta > 0 ? (delta / 10) : 0;
-        }
-        return 0;
-    }
-
-    /**
-     * Returns true if computeFreshnessLifetime used a heuristic. If we used a
-     * heuristic to serve a cached response older than 24 hours, we are required
-     * to attach a warning.
-     */
-    private boolean isFreshnessLifetimeHeuristic() {
-        return maxAgeSeconds == -1 && expires == null;
-    }
-
-    /**
-     * Returns true if this response can be stored to later serve another
-     * request.
-     */
-    public boolean isCacheable(RequestHeaders request) {
-        /*
-         * Always go to network for uncacheable response codes (RFC 2616, 13.4),
-         * This implementation doesn't support caching partial content.
-         */
-        int responseCode = headers.getResponseCode();
-        if (responseCode != HttpURLConnection.HTTP_OK
-                && responseCode != HttpURLConnection.HTTP_NOT_AUTHORITATIVE
-                && responseCode != HttpURLConnection.HTTP_MULT_CHOICE
-                && responseCode != HttpURLConnection.HTTP_MOVED_PERM
-                && responseCode != HttpURLConnection.HTTP_GONE) {
-            return false;
-        }
-
-        /*
-         * Responses to authorized requests aren't cacheable unless they include
-         * a 'public', 'must-revalidate' or 's-maxage' directive.
-         */
-        if (request.hasAuthorization()
-                && !isPublic
-                && !mustRevalidate
-                && sMaxAgeSeconds == -1) {
-            return false;
-        }
-
-        if (noStore) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Returns true if a Vary header contains an asterisk. Such responses cannot
-     * be cached.
-     */
-    public boolean hasVaryAll() {
-        return varyFields.contains("*");
-    }
-
-    /**
-     * Returns true if none of the Vary headers on this response have changed
-     * between {@code cachedRequest} and {@code newRequest}.
-     */
-    public boolean varyMatches(Map<String, List<String>> cachedRequest,
-            Map<String, List<String>> newRequest) {
-        for (String field : varyFields) {
-            if (!Objects.equal(cachedRequest.get(field), newRequest.get(field))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Returns the source to satisfy {@code request} given this cached response.
-     */
-    public ResponseSource chooseResponseSource(long nowMillis, RequestHeaders request) {
-        /*
-         * If this response shouldn't have been stored, it should never be used
-         * as a response source. This check should be redundant as long as the
-         * persistence store is well-behaved and the rules are constant.
-         */
-        if (!isCacheable(request)) {
-            return ResponseSource.NETWORK;
-        }
-
-        if (request.isNoCache() || request.hasConditions()) {
-            return ResponseSource.NETWORK;
-        }
-
-        long ageMillis = computeAge(nowMillis);
-        long freshMillis = computeFreshnessLifetime();
-
-        if (request.getMaxAgeSeconds() != -1) {
-            freshMillis = Math.min(freshMillis,
-                    TimeUnit.SECONDS.toMillis(request.getMaxAgeSeconds()));
-        }
-
-        long minFreshMillis = 0;
-        if (request.getMinFreshSeconds() != -1) {
-            minFreshMillis = TimeUnit.SECONDS.toMillis(request.getMinFreshSeconds());
-        }
-
-        long maxStaleMillis = 0;
-        if (!mustRevalidate && request.getMaxStaleSeconds() != -1) {
-            maxStaleMillis = TimeUnit.SECONDS.toMillis(request.getMaxStaleSeconds());
-        }
-
-        if (!noCache && ageMillis + minFreshMillis < freshMillis + maxStaleMillis) {
-            if (ageMillis + minFreshMillis >= freshMillis) {
-                headers.add("Warning", "110 HttpURLConnection \"Response is stale\"");
-            }
-            if (ageMillis > TimeUnit.HOURS.toMillis(24) && isFreshnessLifetimeHeuristic()) {
-                headers.add("Warning", "113 HttpURLConnection \"Heuristic expiration\"");
-            }
-            return ResponseSource.CACHE;
-        }
-
-        if (lastModified != null) {
-            request.setIfModifiedSince(lastModified);
-        } else if (servedDate != null) {
-            request.setIfModifiedSince(servedDate);
-        }
-
-        if (etag != null) {
-            request.setIfNoneMatch(etag);
-        }
-
-        return request.hasConditions()
-                ? ResponseSource.CONDITIONAL_CACHE
-                : ResponseSource.NETWORK;
-    }
-
-    /**
-     * Returns true if this cached response should be used; false if the
-     * network response should be used.
-     */
-    public boolean validate(ResponseHeaders networkResponse) {
-        if (networkResponse.headers.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
-            return true;
-        }
-
-        /*
-         * The HTTP spec says that if the network's response is older than our
-         * cached response, we may return the cache's response. Like Chrome (but
-         * unlike Firefox), this client prefers to return the newer response.
-         */
-        if (lastModified != null
-                && networkResponse.lastModified != null
-                && networkResponse.lastModified.getTime() < lastModified.getTime()) {
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Combines this cached header with a network header as defined by RFC 2616,
-     * 13.5.3.
-     */
-    public ResponseHeaders combine(ResponseHeaders network) {
-        RawHeaders result = new RawHeaders();
-        result.setStatusLine(headers.getStatusLine());
-
-        for (int i = 0; i < headers.length(); i++) {
-            String fieldName = headers.getFieldName(i);
-            String value = headers.getValue(i);
-            if (fieldName.equals("Warning") && value.startsWith("1")) {
-                continue; // drop 100-level freshness warnings
-            }
-            if (!isEndToEnd(fieldName) || network.headers.get(fieldName) == null) {
-                result.add(fieldName, value);
-            }
-        }
-
-        for (int i = 0; i < network.headers.length(); i++) {
-            String fieldName = network.headers.getFieldName(i);
-            if (isEndToEnd(fieldName)) {
-                result.add(fieldName, network.headers.getValue(i));
-            }
-        }
-
-        return new ResponseHeaders(uri, result);
-    }
-
-    /**
-     * Returns true if {@code fieldName} is an end-to-end HTTP header, as
-     * defined by RFC 2616, 13.5.1.
-     */
-    private static boolean isEndToEnd(String fieldName) {
-        return !fieldName.equalsIgnoreCase("Connection")
-                && !fieldName.equalsIgnoreCase("Keep-Alive")
-                && !fieldName.equalsIgnoreCase("Proxy-Authenticate")
-                && !fieldName.equalsIgnoreCase("Proxy-Authorization")
-                && !fieldName.equalsIgnoreCase("TE")
-                && !fieldName.equalsIgnoreCase("Trailers")
-                && !fieldName.equalsIgnoreCase("Transfer-Encoding")
-                && !fieldName.equalsIgnoreCase("Upgrade");
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/RetryableOutputStream.java b/luni/src/main/java/libcore/net/http/RetryableOutputStream.java
deleted file mode 100644
index 67bb5b8..0000000
--- a/luni/src/main/java/libcore/net/http/RetryableOutputStream.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-
-/**
- * An HTTP request body that's completely buffered in memory. This allows
- * the post body to be transparently re-sent if the HTTP request must be
- * sent multiple times.
- */
-final class RetryableOutputStream extends AbstractHttpOutputStream {
-    private final int limit;
-    private final ByteArrayOutputStream content;
-
-    public RetryableOutputStream(int limit) {
-        this.limit = limit;
-        this.content = new ByteArrayOutputStream(limit);
-    }
-
-    public RetryableOutputStream() {
-        this.limit = -1;
-        this.content = new ByteArrayOutputStream();
-    }
-
-    @Override public synchronized void close() throws IOException {
-        if (closed) {
-            return;
-        }
-        closed = true;
-        if (content.size() < limit) {
-            throw new IOException("content-length promised "
-                    + limit + " bytes, but received " + content.size());
-        }
-    }
-
-    @Override public synchronized void write(byte[] buffer, int offset, int count)
-            throws IOException {
-        checkNotClosed();
-        Arrays.checkOffsetAndCount(buffer.length, offset, count);
-        if (limit != -1 && content.size() > limit - count) {
-            throw new IOException("exceeded content-length limit of " + limit + " bytes");
-        }
-        content.write(buffer, offset, count);
-    }
-
-    public synchronized int contentLength() throws IOException {
-        close();
-        return content.size();
-    }
-
-    public void writeToSocket(OutputStream socketOut) throws IOException  {
-        content.writeTo(socketOut);
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/UnknownLengthHttpInputStream.java b/luni/src/main/java/libcore/net/http/UnknownLengthHttpInputStream.java
deleted file mode 100644
index a8224a3..0000000
--- a/luni/src/main/java/libcore/net/http/UnknownLengthHttpInputStream.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.CacheRequest;
-import java.util.Arrays;
-
-/**
- * An HTTP payload terminated by the end of the socket stream.
- */
-final class UnknownLengthHttpInputStream extends AbstractHttpInputStream {
-    private boolean inputExhausted;
-
-    UnknownLengthHttpInputStream(InputStream is, CacheRequest cacheRequest,
-            HttpEngine httpEngine) throws IOException {
-        super(is, httpEngine, cacheRequest);
-    }
-
-    @Override public int read(byte[] buffer, int offset, int count) throws IOException {
-        Arrays.checkOffsetAndCount(buffer.length, offset, count);
-        checkNotClosed();
-        if (in == null || inputExhausted) {
-            return -1;
-        }
-        int read = in.read(buffer, offset, count);
-        if (read == -1) {
-            inputExhausted = true;
-            endOfInput(false);
-            return -1;
-        }
-        cacheWrite(buffer, offset, read);
-        return read;
-    }
-
-    @Override public int available() throws IOException {
-        checkNotClosed();
-        return in == null ? 0 : in.available();
-    }
-
-    @Override public void close() throws IOException {
-        if (closed) {
-            return;
-        }
-        closed = true;
-        if (!inputExhausted) {
-            unexpectedEndOfInput();
-        }
-    }
-}
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index 1f2ebf9..ac38eb8 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -16,14 +16,11 @@
 
 package libcore.java.net;
 
+import com.android.okhttp.internal.http.HttpResponseCache;
 import com.google.mockwebserver.MockResponse;
 import com.google.mockwebserver.MockWebServer;
 import com.google.mockwebserver.RecordedRequest;
 import com.google.mockwebserver.SocketPolicy;
-import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END;
-import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_START;
-import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END;
-import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END;
 import dalvik.system.CloseGuard;
 import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
@@ -49,21 +46,15 @@
 import java.net.UnknownHostException;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
-import java.util.TimeZone;
 import java.util.UUID;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.zip.GZIPInputStream;
@@ -81,9 +72,13 @@
 import libcore.java.lang.ref.FinalizationTester;
 import libcore.java.security.TestKeyStore;
 import libcore.javax.net.ssl.TestSSLContext;
-import libcore.net.http.HttpResponseCache;
 import tests.net.StuckServer;
 
+import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END;
+import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_START;
+import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END;
+import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END;
+
 public final class URLConnectionTest extends TestCase {
     private MockWebServer server = new MockWebServer();
     private HttpResponseCache cache;
diff --git a/luni/src/test/java/libcore/net/http/HttpResponseCacheTest.java b/luni/src/test/java/libcore/net/http/HttpResponseCacheTest.java
deleted file mode 100644
index 133924e..0000000
--- a/luni/src/test/java/libcore/net/http/HttpResponseCacheTest.java
+++ /dev/null
@@ -1,1886 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import com.google.mockwebserver.MockResponse;
-import com.google.mockwebserver.MockWebServer;
-import com.google.mockwebserver.RecordedRequest;
-import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.lang.reflect.InvocationHandler;
-import java.net.CacheRequest;
-import java.net.CacheResponse;
-import java.net.CookieHandler;
-import java.net.CookieManager;
-import java.net.HttpCookie;
-import java.net.HttpURLConnection;
-import java.net.ResponseCache;
-import java.net.SecureCacheResponse;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.security.Principal;
-import java.security.cert.Certificate;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Deque;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.zip.GZIPOutputStream;
-import javax.net.ssl.HttpsURLConnection;
-import junit.framework.TestCase;
-import libcore.javax.net.ssl.TestSSLContext;
-import tests.io.MockOs;
-
-public final class HttpResponseCacheTest extends TestCase {
-    private MockWebServer server = new MockWebServer();
-    private HttpResponseCache cache;
-    private final MockOs mockOs = new MockOs();
-    private final CookieManager cookieManager = new CookieManager();
-
-    @Override protected void setUp() throws Exception {
-        super.setUp();
-
-        String tmp = System.getProperty("java.io.tmpdir");
-        File cacheDir = new File(tmp, "HttpCache-" + UUID.randomUUID());
-        cache = new HttpResponseCache(cacheDir, Integer.MAX_VALUE);
-        ResponseCache.setDefault(cache);
-        mockOs.install();
-        CookieHandler.setDefault(cookieManager);
-    }
-
-    @Override protected void tearDown() throws Exception {
-        mockOs.uninstall();
-        server.shutdown();
-        ResponseCache.setDefault(null);
-        cache.getCache().delete();
-        CookieHandler.setDefault(null);
-        super.tearDown();
-    }
-
-    /**
-     * Test that response caching is consistent with the RI and the spec.
-     * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4
-     */
-    public void testResponseCachingByResponseCode() throws Exception {
-        // Test each documented HTTP/1.1 code, plus the first unused value in each range.
-        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
-
-        // We can't test 100 because it's not really a response.
-        // assertCached(false, 100);
-        assertCached(false, 101);
-        assertCached(false, 102);
-        assertCached(true,  200);
-        assertCached(false, 201);
-        assertCached(false, 202);
-        assertCached(true,  203);
-        assertCached(false, 204);
-        assertCached(false, 205);
-        assertCached(false, 206); // we don't cache partial responses
-        assertCached(false, 207);
-        assertCached(true,  300);
-        assertCached(true,  301);
-        for (int i = 302; i <= 308; ++i) {
-            assertCached(false, i);
-        }
-        for (int i = 400; i <= 406; ++i) {
-            assertCached(false, i);
-        }
-        // (See test_responseCaching_407.)
-        assertCached(false, 408);
-        assertCached(false, 409);
-        // (See test_responseCaching_410.)
-        for (int i = 411; i <= 418; ++i) {
-            assertCached(false, i);
-        }
-        for (int i = 500; i <= 506; ++i) {
-            assertCached(false, i);
-        }
-    }
-
-    /**
-     * Response code 407 should only come from proxy servers. Android's client
-     * throws if it is sent by an origin server.
-     */
-    public void testOriginServerSends407() throws Exception {
-        server.enqueue(new MockResponse().setResponseCode(407));
-        server.play();
-
-        URL url = server.getUrl("/");
-        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-        try {
-            conn.getResponseCode();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void test_responseCaching_410() throws Exception {
-        // the HTTP spec permits caching 410s, but the RI doesn't.
-        assertCached(true, 410);
-    }
-
-    private void assertCached(boolean shouldPut, int responseCode) throws Exception {
-        server = new MockWebServer();
-        MockResponse response = new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setResponseCode(responseCode)
-                .setBody("ABCDE")
-                .addHeader("WWW-Authenticate: challenge");
-        if (responseCode == HttpURLConnection.HTTP_PROXY_AUTH) {
-            response.addHeader("Proxy-Authenticate: Basic realm=\"protected area\"");
-        } else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
-            response.addHeader("WWW-Authenticate: Basic realm=\"protected area\"");
-        }
-        server.enqueue(response);
-        server.play();
-
-        URL url = server.getUrl("/");
-        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-        assertEquals(responseCode, conn.getResponseCode());
-
-        // exhaust the content stream
-        readAscii(conn);
-
-        CacheResponse cached = cache.get(url.toURI(), "GET",
-                Collections.<String, List<String>>emptyMap());
-        if (shouldPut) {
-            assertNotNull(Integer.toString(responseCode), cached);
-            cached.getBody().close();
-        } else {
-            assertNull(Integer.toString(responseCode), cached);
-        }
-        server.shutdown(); // tearDown() isn't sufficient; this test starts multiple servers
-    }
-
-    /**
-     * Test that we can interrogate the response when the cache is being
-     * populated. http://code.google.com/p/android/issues/detail?id=7787
-     */
-    public void testResponseCacheCallbackApis() throws Exception {
-        final String body = "ABCDE";
-        final AtomicInteger cacheCount = new AtomicInteger();
-
-        server.enqueue(new MockResponse()
-                .setStatus("HTTP/1.1 200 Fantastic")
-                .addHeader("fgh: ijk")
-                .setBody(body));
-        server.play();
-
-        ResponseCache.setDefault(new ResponseCache() {
-            @Override public CacheResponse get(URI uri, String requestMethod,
-                    Map<String, List<String>> requestHeaders) throws IOException {
-                return null;
-            }
-            @Override public CacheRequest put(URI uri, URLConnection conn) throws IOException {
-                HttpURLConnection httpConnection = (HttpURLConnection) conn;
-                try {
-                    httpConnection.getRequestProperties();
-                    fail();
-                } catch (IllegalStateException expected) {
-                }
-                try {
-                    httpConnection.addRequestProperty("K", "V");
-                    fail();
-                } catch (IllegalStateException expected) {
-                }
-                assertEquals("HTTP/1.1 200 Fantastic", httpConnection.getHeaderField(null));
-                assertEquals(Arrays.asList("HTTP/1.1 200 Fantastic"),
-                        httpConnection.getHeaderFields().get(null));
-                assertEquals(200, httpConnection.getResponseCode());
-                assertEquals("Fantastic", httpConnection.getResponseMessage());
-                assertEquals(body.length(), httpConnection.getContentLength());
-                assertEquals("ijk", httpConnection.getHeaderField("fgh"));
-                try {
-                    httpConnection.getInputStream(); // the RI doesn't forbid this, but it should
-                    fail();
-                } catch (IOException expected) {
-                }
-                cacheCount.incrementAndGet();
-                return null;
-            }
-        });
-
-        URL url = server.getUrl("/");
-        URLConnection connection = url.openConnection();
-        assertEquals(body, readAscii(connection));
-        assertEquals(1, cacheCount.get());
-    }
-
-
-    public void testResponseCachingAndInputStreamSkipWithFixedLength() throws IOException {
-        testResponseCaching(TransferKind.FIXED_LENGTH);
-    }
-
-    public void testResponseCachingAndInputStreamSkipWithChunkedEncoding() throws IOException {
-        testResponseCaching(TransferKind.CHUNKED);
-    }
-
-    public void testResponseCachingAndInputStreamSkipWithNoLengthHeaders() throws IOException {
-        testResponseCaching(TransferKind.END_OF_STREAM);
-    }
-
-    /**
-     * HttpURLConnection.getInputStream().skip(long) causes ResponseCache corruption
-     * http://code.google.com/p/android/issues/detail?id=8175
-     */
-    private void testResponseCaching(TransferKind transferKind) throws IOException {
-        MockResponse response = new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setStatus("HTTP/1.1 200 Fantastic");
-        transferKind.setBody(response, "I love puppies but hate spiders", 1);
-        server.enqueue(response);
-        server.play();
-
-        // Make sure that calling skip() doesn't omit bytes from the cache.
-        HttpURLConnection urlConnection = (HttpURLConnection) server.getUrl("/").openConnection();
-        InputStream in = urlConnection.getInputStream();
-        assertEquals("I love ", readAscii(urlConnection, "I love ".length()));
-        reliableSkip(in, "puppies but hate ".length());
-        assertEquals("spiders", readAscii(urlConnection, "spiders".length()));
-        assertEquals(-1, in.read());
-        in.close();
-        assertEquals(1, cache.getWriteSuccessCount());
-        assertEquals(0, cache.getWriteAbortCount());
-
-        urlConnection = (HttpURLConnection) server.getUrl("/").openConnection(); // cached!
-        in = urlConnection.getInputStream();
-        assertEquals("I love puppies but hate spiders",
-                readAscii(urlConnection, "I love puppies but hate spiders".length()));
-        assertEquals(200, urlConnection.getResponseCode());
-        assertEquals("Fantastic", urlConnection.getResponseMessage());
-
-        assertEquals(-1, in.read());
-        in.close();
-        assertEquals(1, cache.getWriteSuccessCount());
-        assertEquals(0, cache.getWriteAbortCount());
-        assertEquals(2, cache.getRequestCount());
-        assertEquals(1, cache.getHitCount());
-    }
-
-    public void testSecureResponseCaching() throws IOException {
-        TestSSLContext testSSLContext = TestSSLContext.create();
-        server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setBody("ABC"));
-        server.play();
-
-        HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
-        connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("ABC", readAscii(connection));
-
-        // OpenJDK 6 fails on this line, complaining that the connection isn't open yet
-        String suite = connection.getCipherSuite();
-        List<Certificate> localCerts = toListOrNull(connection.getLocalCertificates());
-        List<Certificate> serverCerts = toListOrNull(connection.getServerCertificates());
-        Principal peerPrincipal = connection.getPeerPrincipal();
-        Principal localPrincipal = connection.getLocalPrincipal();
-
-        connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // cached!
-        connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("ABC", readAscii(connection));
-
-        assertEquals(2, cache.getRequestCount());
-        assertEquals(1, cache.getNetworkCount());
-        assertEquals(1, cache.getHitCount());
-
-        assertEquals(suite, connection.getCipherSuite());
-        assertEquals(localCerts, toListOrNull(connection.getLocalCertificates()));
-        assertEquals(serverCerts, toListOrNull(connection.getServerCertificates()));
-        assertEquals(peerPrincipal, connection.getPeerPrincipal());
-        assertEquals(localPrincipal, connection.getLocalPrincipal());
-    }
-
-    public void testCacheReturnsInsecureResponseForSecureRequest() throws IOException {
-        TestSSLContext testSSLContext = TestSSLContext.create();
-        server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
-        server.enqueue(new MockResponse().setBody("ABC"));
-        server.enqueue(new MockResponse().setBody("DEF"));
-        server.play();
-
-        ResponseCache.setDefault(new InsecureResponseCache());
-
-        HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
-        connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("ABC", readAscii(connection));
-
-        connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // not cached!
-        connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("DEF", readAscii(connection));
-    }
-
-    public void testResponseCachingAndRedirects() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)
-                .addHeader("Location: /foo"));
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setBody("ABC"));
-        server.enqueue(new MockResponse().setBody("DEF"));
-        server.play();
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        assertEquals("ABC", readAscii(connection));
-
-        connection = server.getUrl("/").openConnection(); // cached!
-        assertEquals("ABC", readAscii(connection));
-
-        assertEquals(4, cache.getRequestCount()); // 2 requests + 2 redirects
-        assertEquals(2, cache.getNetworkCount());
-        assertEquals(2, cache.getHitCount());
-    }
-
-    public void testRedirectToCachedResult() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("ABC"));
-        server.enqueue(new MockResponse()
-                .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)
-                .addHeader("Location: /foo"));
-        server.enqueue(new MockResponse().setBody("DEF"));
-        server.play();
-
-        assertEquals("ABC", readAscii(server.getUrl("/foo").openConnection()));
-        RecordedRequest request1 = server.takeRequest();
-        assertEquals("GET /foo HTTP/1.1", request1.getRequestLine());
-        assertEquals(0, request1.getSequenceNumber());
-
-        assertEquals("ABC", readAscii(server.getUrl("/bar").openConnection()));
-        RecordedRequest request2 = server.takeRequest();
-        assertEquals("GET /bar HTTP/1.1", request2.getRequestLine());
-        assertEquals(1, request2.getSequenceNumber());
-
-        // an unrelated request should reuse the pooled connection
-        assertEquals("DEF", readAscii(server.getUrl("/baz").openConnection()));
-        RecordedRequest request3 = server.takeRequest();
-        assertEquals("GET /baz HTTP/1.1", request3.getRequestLine());
-        assertEquals(2, request3.getSequenceNumber());
-    }
-
-    public void testSecureResponseCachingAndRedirects() throws IOException {
-        TestSSLContext testSSLContext = TestSSLContext.create();
-        server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)
-                .addHeader("Location: /foo"));
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setBody("ABC"));
-        server.enqueue(new MockResponse().setBody("DEF"));
-        server.play();
-
-        HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
-        connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("ABC", readAscii(connection));
-
-        connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // cached!
-        connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("ABC", readAscii(connection));
-
-        assertEquals(4, cache.getRequestCount()); // 2 direct + 2 redirect = 4
-        assertEquals(2, cache.getHitCount());
-    }
-
-    public void testResponseCacheRequestHeaders() throws IOException, URISyntaxException {
-        server.enqueue(new MockResponse().setBody("ABC"));
-        server.play();
-
-        final AtomicReference<Map<String, List<String>>> requestHeadersRef
-                = new AtomicReference<Map<String, List<String>>>();
-        ResponseCache.setDefault(new ResponseCache() {
-            @Override public CacheResponse get(URI uri, String requestMethod,
-                    Map<String, List<String>> requestHeaders) throws IOException {
-                requestHeadersRef.set(requestHeaders);
-                return null;
-            }
-            @Override public CacheRequest put(URI uri, URLConnection conn) throws IOException {
-                return null;
-            }
-        });
-
-        URL url = server.getUrl("/");
-        URLConnection urlConnection = url.openConnection();
-        urlConnection.addRequestProperty("A", "android");
-        readAscii(urlConnection);
-        assertEquals(Arrays.asList("android"), requestHeadersRef.get().get("A"));
-    }
-
-
-    public void testServerDisconnectsPrematurelyWithContentLengthHeader() throws IOException {
-        testServerPrematureDisconnect(TransferKind.FIXED_LENGTH);
-    }
-
-    public void testServerDisconnectsPrematurelyWithChunkedEncoding() throws IOException {
-        testServerPrematureDisconnect(TransferKind.CHUNKED);
-    }
-
-    public void testServerDisconnectsPrematurelyWithNoLengthHeaders() throws IOException {
-        /*
-         * Intentionally empty. This case doesn't make sense because there's no
-         * such thing as a premature disconnect when the disconnect itself
-         * indicates the end of the data stream.
-         */
-    }
-
-    private void testServerPrematureDisconnect(TransferKind transferKind) throws IOException {
-        MockResponse response = new MockResponse();
-        transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 16);
-        server.enqueue(truncateViolently(response, 16));
-        server.enqueue(new MockResponse().setBody("Request #2"));
-        server.play();
-
-        BufferedReader reader = new BufferedReader(new InputStreamReader(
-                server.getUrl("/").openConnection().getInputStream()));
-        assertEquals("ABCDE", reader.readLine());
-        try {
-            reader.readLine();
-            fail("This implementation silently ignored a truncated HTTP body.");
-        } catch (IOException expected) {
-        } finally {
-            reader.close();
-        }
-
-        assertEquals(1, cache.getWriteAbortCount());
-        assertEquals(0, cache.getWriteSuccessCount());
-        URLConnection connection = server.getUrl("/").openConnection();
-        assertEquals("Request #2", readAscii(connection));
-        assertEquals(1, cache.getWriteAbortCount());
-        assertEquals(1, cache.getWriteSuccessCount());
-    }
-
-    public void testClientPrematureDisconnectWithContentLengthHeader() throws IOException {
-        testClientPrematureDisconnect(TransferKind.FIXED_LENGTH);
-    }
-
-    public void testClientPrematureDisconnectWithChunkedEncoding() throws IOException {
-        testClientPrematureDisconnect(TransferKind.CHUNKED);
-    }
-
-    public void testClientPrematureDisconnectWithNoLengthHeaders() throws IOException {
-        testClientPrematureDisconnect(TransferKind.END_OF_STREAM);
-    }
-
-    private void testClientPrematureDisconnect(TransferKind transferKind) throws IOException {
-        MockResponse response = new MockResponse();
-        transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 1024);
-        server.enqueue(response);
-        server.enqueue(new MockResponse().setBody("Request #2"));
-        server.play();
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        InputStream in = connection.getInputStream();
-        assertEquals("ABCDE", readAscii(connection, 5));
-        in.close();
-        try {
-            in.read();
-            fail("Expected an IOException because the stream is closed.");
-        } catch (IOException expected) {
-        }
-
-        assertEquals(1, cache.getWriteAbortCount());
-        assertEquals(0, cache.getWriteSuccessCount());
-        connection = server.getUrl("/").openConnection();
-        assertEquals("Request #2", readAscii(connection));
-        assertEquals(1, cache.getWriteAbortCount());
-        assertEquals(1, cache.getWriteSuccessCount());
-    }
-
-    public void testDefaultExpirationDateFullyCachedForLessThan24Hours() throws Exception {
-        //      last modified: 105 seconds ago
-        //             served:   5 seconds ago
-        //   default lifetime: (105 - 5) / 10 = 10 seconds
-        //            expires:  10 seconds from served date = 5 seconds from now
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS))
-                .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS))
-                .setBody("A"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-        URLConnection connection = url.openConnection();
-        assertEquals("A", readAscii(connection));
-        assertNull(connection.getHeaderField("Warning"));
-    }
-
-    public void testDefaultExpirationDateConditionallyCached() throws Exception {
-        //      last modified: 115 seconds ago
-        //             served:  15 seconds ago
-        //   default lifetime: (115 - 15) / 10 = 10 seconds
-        //            expires:  10 seconds from served date = 5 seconds ago
-        String lastModifiedDate = formatDate(-115, TimeUnit.SECONDS);
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Date: " + formatDate(-15, TimeUnit.SECONDS)));
-        List<String> headers = conditionalRequest.getHeaders();
-        assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    public void testDefaultExpirationDateFullyCachedForMoreThan24Hours() throws Exception {
-        //      last modified: 105 days ago
-        //             served:   5 days ago
-        //   default lifetime: (105 - 5) / 10 = 10 days
-        //            expires:  10 days from served date = 5 days from now
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.DAYS))
-                .addHeader("Date: " + formatDate(-5, TimeUnit.DAYS))
-                .setBody("A"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        URLConnection connection = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection));
-        assertEquals("113 HttpURLConnection \"Heuristic expiration\"",
-                connection.getHeaderField("Warning"));
-    }
-
-    public void testNoDefaultExpirationForUrlsWithQueryString() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS))
-                .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS))
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/?foo=bar");
-        assertEquals("A", readAscii(url.openConnection()));
-        assertEquals("B", readAscii(url.openConnection()));
-    }
-
-    public void testExpirationDateInThePastWithLastModifiedHeader() throws Exception {
-        String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
-        List<String> headers = conditionalRequest.getHeaders();
-        assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    public void testExpirationDateInThePastWithNoLastModifiedHeader() throws Exception {
-        assertNotCached(new MockResponse()
-                .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
-    }
-
-    public void testExpirationDateInTheFuture() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
-    }
-
-    public void testMaxAgePreferredWithMaxAgeAndExpires() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Date: " + formatDate(0, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testMaxAgeInThePastWithDateAndLastModifiedHeaders() throws Exception {
-        String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS))
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Cache-Control: max-age=60"));
-        List<String> headers = conditionalRequest.getHeaders();
-        assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    public void testMaxAgeInThePastWithDateHeaderButNoLastModifiedHeader() throws Exception {
-        /*
-         * Chrome interprets max-age relative to the local clock. Both our cache
-         * and Firefox both use the earlier of the local and server's clock.
-         */
-        assertNotCached(new MockResponse()
-                .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS))
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testMaxAgeInTheFutureWithDateHeader() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Date: " + formatDate(0, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testMaxAgeInTheFutureWithNoDateHeader() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testMaxAgeWithLastModifiedButNoServedDate() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS))
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testMaxAgeInTheFutureWithDateAndLastModifiedHeaders() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS))
-                .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS))
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testMaxAgePreferredOverLowerSharedMaxAge() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES))
-                .addHeader("Cache-Control: s-maxage=60")
-                .addHeader("Cache-Control: max-age=180"));
-    }
-
-    public void testMaxAgePreferredOverHigherMaxAge() throws Exception {
-        assertNotCached(new MockResponse()
-                .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES))
-                .addHeader("Cache-Control: s-maxage=180")
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testRequestMethodOptionsIsNotCached() throws Exception {
-        testRequestMethod("OPTIONS", false);
-    }
-
-    public void testRequestMethodGetIsCached() throws Exception {
-        testRequestMethod("GET", true);
-    }
-
-    public void testRequestMethodHeadIsNotCached() throws Exception {
-        // We could support this but choose not to for implementation simplicity
-        testRequestMethod("HEAD", false);
-    }
-
-    public void testRequestMethodPostIsNotCached() throws Exception {
-        // We could support this but choose not to for implementation simplicity
-        testRequestMethod("POST", false);
-    }
-
-    public void testRequestMethodPutIsNotCached() throws Exception {
-        testRequestMethod("PUT", false);
-    }
-
-    public void testRequestMethodDeleteIsNotCached() throws Exception {
-        testRequestMethod("DELETE", false);
-    }
-
-    public void testRequestMethodTraceIsNotCached() throws Exception {
-        testRequestMethod("TRACE", false);
-    }
-
-    private void testRequestMethod(String requestMethod, boolean expectCached) throws Exception {
-        /*
-         * 1. seed the cache (potentially)
-         * 2. expect a cache hit or miss
-         */
-        server.enqueue(new MockResponse()
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .addHeader("X-Response-ID: 1"));
-        server.enqueue(new MockResponse()
-                .addHeader("X-Response-ID: 2"));
-        server.play();
-
-        URL url = server.getUrl("/");
-
-        HttpURLConnection request1 = (HttpURLConnection) url.openConnection();
-        request1.setRequestMethod(requestMethod);
-        addRequestBodyIfNecessary(requestMethod, request1);
-        assertEquals("1", request1.getHeaderField("X-Response-ID"));
-
-        URLConnection request2 = url.openConnection();
-        if (expectCached) {
-            assertEquals("1", request1.getHeaderField("X-Response-ID"));
-        } else {
-            assertEquals("2", request2.getHeaderField("X-Response-ID"));
-        }
-    }
-
-    public void testPostInvalidatesCache() throws Exception {
-        testMethodInvalidates("POST");
-    }
-
-    public void testPutInvalidatesCache() throws Exception {
-        testMethodInvalidates("PUT");
-    }
-
-    public void testDeleteMethodInvalidatesCache() throws Exception {
-        testMethodInvalidates("DELETE");
-    }
-
-    private void testMethodInvalidates(String requestMethod) throws Exception {
-        /*
-         * 1. seed the cache
-         * 2. invalidate it
-         * 3. expect a cache miss
-         */
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.enqueue(new MockResponse().setBody("C"));
-        server.play();
-
-        URL url = server.getUrl("/");
-
-        assertEquals("A", readAscii(url.openConnection()));
-
-        HttpURLConnection invalidate = (HttpURLConnection) url.openConnection();
-        invalidate.setRequestMethod(requestMethod);
-        addRequestBodyIfNecessary(requestMethod, invalidate);
-        assertEquals("B", readAscii(invalidate));
-
-        assertEquals("C", readAscii(url.openConnection()));
-    }
-
-    public void testEtag() throws Exception {
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("ETag: v1"));
-        assertTrue(conditionalRequest.getHeaders().contains("If-None-Match: v1"));
-    }
-
-    public void testEtagAndExpirationDateInThePast() throws Exception {
-        String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("ETag: v1")
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
-        List<String> headers = conditionalRequest.getHeaders();
-        assertTrue(headers.contains("If-None-Match: v1"));
-        assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    public void testEtagAndExpirationDateInTheFuture() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("ETag: v1")
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
-    }
-
-    public void testCacheControlNoCache() throws Exception {
-        assertNotCached(new MockResponse().addHeader("Cache-Control: no-cache"));
-    }
-
-    public void testCacheControlNoCacheAndExpirationDateInTheFuture() throws Exception {
-        String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: no-cache"));
-        List<String> headers = conditionalRequest.getHeaders();
-        assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    public void testPragmaNoCache() throws Exception {
-        assertNotCached(new MockResponse().addHeader("Pragma: no-cache"));
-    }
-
-    public void testPragmaNoCacheAndExpirationDateInTheFuture() throws Exception {
-        String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .addHeader("Pragma: no-cache"));
-        List<String> headers = conditionalRequest.getHeaders();
-        assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    public void testCacheControlNoStore() throws Exception {
-        assertNotCached(new MockResponse().addHeader("Cache-Control: no-store"));
-    }
-
-    public void testCacheControlNoStoreAndExpirationDateInTheFuture() throws Exception {
-        assertNotCached(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: no-store"));
-    }
-
-    public void testPartialRangeResponsesDoNotCorruptCache() throws Exception {
-        /*
-         * 1. request a range
-         * 2. request a full document, expecting a cache miss
-         */
-        server.enqueue(new MockResponse().setBody("AA")
-                .setResponseCode(HttpURLConnection.HTTP_PARTIAL)
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .addHeader("Content-Range: bytes 1000-1001/2000"));
-        server.enqueue(new MockResponse().setBody("BB"));
-        server.play();
-
-        URL url = server.getUrl("/");
-
-        URLConnection range = url.openConnection();
-        range.addRequestProperty("Range", "bytes=1000-1001");
-        assertEquals("AA", readAscii(range));
-
-        assertEquals("BB", readAscii(url.openConnection()));
-    }
-
-    public void testServerReturnsDocumentOlderThanCache() throws Exception {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
-        server.enqueue(new MockResponse().setBody("B")
-                .addHeader("Last-Modified: " + formatDate(-4, TimeUnit.HOURS)));
-        server.play();
-
-        URL url = server.getUrl("/");
-
-        assertEquals("A", readAscii(url.openConnection()));
-        assertEquals("A", readAscii(url.openConnection()));
-    }
-
-    public void testNonIdentityEncodingAndConditionalCache() throws Exception {
-        assertNonIdentityEncodingCached(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
-    }
-
-    public void testNonIdentityEncodingAndFullCache() throws Exception {
-        assertNonIdentityEncodingCached(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
-    }
-
-    private void assertNonIdentityEncodingCached(MockResponse response) throws Exception {
-        server.enqueue(response
-                .setBody(gzip("ABCABCABC".getBytes("UTF-8")))
-                .addHeader("Content-Encoding: gzip"));
-        server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-
-        server.play();
-        assertEquals("ABCABCABC", readAscii(server.getUrl("/").openConnection()));
-        assertEquals("ABCABCABC", readAscii(server.getUrl("/").openConnection()));
-    }
-
-    public void testExpiresDateBeforeModifiedDate() throws Exception {
-        assertConditionallyCached(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(-2, TimeUnit.HOURS)));
-    }
-
-    public void testRequestMaxAge() throws IOException {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
-                .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
-        server.enqueue(new MockResponse().setBody("B"));
-
-        server.play();
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "max-age=30");
-        assertEquals("B", readAscii(connection));
-    }
-
-    public void testRequestMinFresh() throws IOException {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES)));
-        server.enqueue(new MockResponse().setBody("B"));
-
-        server.play();
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "min-fresh=120");
-        assertEquals("B", readAscii(connection));
-    }
-
-    public void testRequestMaxStale() throws IOException {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Cache-Control: max-age=120")
-                .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES)));
-        server.enqueue(new MockResponse().setBody("B"));
-
-        server.play();
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "max-stale=180");
-        assertEquals("A", readAscii(connection));
-        assertEquals("110 HttpURLConnection \"Response is stale\"",
-                connection.getHeaderField("Warning"));
-    }
-
-    public void testRequestMaxStaleNotHonoredWithMustRevalidate() throws IOException {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Cache-Control: max-age=120, must-revalidate")
-                .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES)));
-        server.enqueue(new MockResponse().setBody("B"));
-
-        server.play();
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "max-stale=180");
-        assertEquals("B", readAscii(connection));
-    }
-
-    public void testRequestOnlyIfCachedWithNoResponseCached() throws IOException {
-        // (no responses enqueued)
-        server.play();
-
-        HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "only-if-cached");
-        assertGatewayTimeout(connection);
-    }
-
-    public void testRequestOnlyIfCachedWithFullResponseCached() throws IOException {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Cache-Control: max-age=30")
-                .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES)));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "only-if-cached");
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-    }
-
-    public void testRequestOnlyIfCachedWithConditionalResponseCached() throws IOException {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Cache-Control: max-age=30")
-                .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES)));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "only-if-cached");
-        assertGatewayTimeout(connection);
-    }
-
-    public void testRequestOnlyIfCachedWithUnhelpfulResponseCached() throws IOException {
-        server.enqueue(new MockResponse().setBody("A"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "only-if-cached");
-        assertGatewayTimeout(connection);
-    }
-
-    public void testRequestCacheControlNoCache() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS))
-                .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS))
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-        URLConnection connection = url.openConnection();
-        connection.setRequestProperty("Cache-Control", "no-cache");
-        assertEquals("B", readAscii(connection));
-    }
-
-    public void testRequestPragmaNoCache() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS))
-                .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS))
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-        URLConnection connection = url.openConnection();
-        connection.setRequestProperty("Pragma", "no-cache");
-        assertEquals("B", readAscii(connection));
-    }
-
-    public void testClientSuppliedIfModifiedSinceWithCachedResult() throws Exception {
-        MockResponse response = new MockResponse()
-                .addHeader("ETag: v3")
-                .addHeader("Cache-Control: max-age=0");
-        String ifModifiedSinceDate = formatDate(-24, TimeUnit.HOURS);
-        RecordedRequest request = assertClientSuppliedCondition(
-                response, "If-Modified-Since", ifModifiedSinceDate);
-        List<String> headers = request.getHeaders();
-        assertTrue(headers.contains("If-Modified-Since: " + ifModifiedSinceDate));
-        assertFalse(headers.contains("If-None-Match: v3"));
-    }
-
-    public void testClientSuppliedIfNoneMatchSinceWithCachedResult() throws Exception {
-        String lastModifiedDate = formatDate(-3, TimeUnit.MINUTES);
-        MockResponse response = new MockResponse()
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES))
-                .addHeader("Cache-Control: max-age=0");
-        RecordedRequest request = assertClientSuppliedCondition(
-                response, "If-None-Match", "v1");
-        List<String> headers = request.getHeaders();
-        assertTrue(headers.contains("If-None-Match: v1"));
-        assertFalse(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    private RecordedRequest assertClientSuppliedCondition(MockResponse seed, String conditionName,
-            String conditionValue) throws Exception {
-        server.enqueue(seed.setBody("A"));
-        server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-
-        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
-        connection.addRequestProperty(conditionName, conditionValue);
-        assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode());
-        assertEquals("", readAscii(connection));
-
-        server.takeRequest(); // seed
-        return server.takeRequest();
-    }
-
-    public void testSetIfModifiedSince() throws Exception {
-        Date since = new Date();
-        server.enqueue(new MockResponse().setBody("A"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection = url.openConnection();
-        connection.setIfModifiedSince(since.getTime());
-        assertEquals("A", readAscii(connection));
-        RecordedRequest request = server.takeRequest();
-        assertTrue(request.getHeaders().contains("If-Modified-Since: " + formatDate(since)));
-    }
-
-    public void testClientSuppliedConditionWithoutCachedResult() throws Exception {
-        server.enqueue(new MockResponse()
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        String clientIfModifiedSince = formatDate(-24, TimeUnit.HOURS);
-        connection.addRequestProperty("If-Modified-Since", clientIfModifiedSince);
-        assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode());
-        assertEquals("", readAscii(connection));
-    }
-
-    public void testAuthorizationRequestHeaderPreventsCaching() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.MINUTES))
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection = url.openConnection();
-        connection.addRequestProperty("Authorization", "password");
-        assertEquals("A", readAscii(connection));
-        assertEquals("B", readAscii(url.openConnection()));
-    }
-
-    public void testAuthorizationResponseCachedWithSMaxAge() throws Exception {
-        assertAuthorizationRequestFullyCached(new MockResponse()
-                .addHeader("Cache-Control: s-maxage=60"));
-    }
-
-    public void testAuthorizationResponseCachedWithPublic() throws Exception {
-        assertAuthorizationRequestFullyCached(new MockResponse()
-                .addHeader("Cache-Control: public"));
-    }
-
-    public void testAuthorizationResponseCachedWithMustRevalidate() throws Exception {
-        assertAuthorizationRequestFullyCached(new MockResponse()
-                .addHeader("Cache-Control: must-revalidate"));
-    }
-
-    public void assertAuthorizationRequestFullyCached(MockResponse response) throws Exception {
-        server.enqueue(response
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection = url.openConnection();
-        connection.addRequestProperty("Authorization", "password");
-        assertEquals("A", readAscii(connection));
-        assertEquals("A", readAscii(url.openConnection()));
-    }
-
-    public void testContentLocationDoesNotPopulateCache() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Content-Location: /bar")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/foo").openConnection()));
-        assertEquals("B", readAscii(server.getUrl("/bar").openConnection()));
-    }
-
-    public void testUseCachesFalseDoesNotWriteToCache() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A").setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.setUseCaches(false);
-        assertEquals("A", readAscii(connection));
-        assertEquals("B", readAscii(server.getUrl("/").openConnection()));
-    }
-
-    public void testUseCachesFalseDoesNotReadFromCache() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A").setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.setUseCaches(false);
-        assertEquals("B", readAscii(connection));
-    }
-
-    public void testDefaultUseCachesSetsInitialValueOnly() throws Exception {
-        URL url = new URL("http://localhost/");
-        URLConnection c1 = url.openConnection();
-        URLConnection c2 = url.openConnection();
-        assertTrue(c1.getDefaultUseCaches());
-        c1.setDefaultUseCaches(false);
-        try {
-            assertTrue(c1.getUseCaches());
-            assertTrue(c2.getUseCaches());
-            URLConnection c3 = url.openConnection();
-            assertFalse(c3.getUseCaches());
-        } finally {
-            c1.setDefaultUseCaches(true);
-        }
-    }
-
-    public void testConnectionIsReturnedToPoolAfterConditionalSuccess() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/a").openConnection()));
-        assertEquals("A", readAscii(server.getUrl("/a").openConnection()));
-        assertEquals("B", readAscii(server.getUrl("/b").openConnection()));
-
-        assertEquals(0, server.takeRequest().getSequenceNumber());
-        assertEquals(1, server.takeRequest().getSequenceNumber());
-        assertEquals(2, server.takeRequest().getSequenceNumber());
-    }
-
-    public void testStatisticsConditionalCacheMiss() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.enqueue(new MockResponse().setBody("C"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals(1, cache.getRequestCount());
-        assertEquals(1, cache.getNetworkCount());
-        assertEquals(0, cache.getHitCount());
-        assertEquals("B", readAscii(server.getUrl("/").openConnection()));
-        assertEquals("C", readAscii(server.getUrl("/").openConnection()));
-        assertEquals(3, cache.getRequestCount());
-        assertEquals(3, cache.getNetworkCount());
-        assertEquals(0, cache.getHitCount());
-    }
-
-    public void testStatisticsConditionalCacheHit() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals(1, cache.getRequestCount());
-        assertEquals(1, cache.getNetworkCount());
-        assertEquals(0, cache.getHitCount());
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals(3, cache.getRequestCount());
-        assertEquals(3, cache.getNetworkCount());
-        assertEquals(2, cache.getHitCount());
-    }
-
-    public void testStatisticsFullCacheHit() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals(1, cache.getRequestCount());
-        assertEquals(1, cache.getNetworkCount());
-        assertEquals(0, cache.getHitCount());
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals(3, cache.getRequestCount());
-        assertEquals(1, cache.getNetworkCount());
-        assertEquals(2, cache.getHitCount());
-    }
-
-    public void testVaryMatchesChangedRequestHeaderField() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        HttpURLConnection frConnection = (HttpURLConnection) url.openConnection();
-        frConnection.addRequestProperty("Accept-Language", "fr-CA");
-        assertEquals("A", readAscii(frConnection));
-
-        HttpURLConnection enConnection = (HttpURLConnection) url.openConnection();
-        enConnection.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("B", readAscii(enConnection));
-    }
-
-    public void testVaryMatchesUnchangedRequestHeaderField() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection1 = url.openConnection();
-        connection1.addRequestProperty("Accept-Language", "fr-CA");
-        assertEquals("A", readAscii(connection1));
-        URLConnection connection2 = url.openConnection();
-        connection2.addRequestProperty("Accept-Language", "fr-CA");
-        assertEquals("A", readAscii(connection2));
-    }
-
-    public void testVaryMatchesAbsentRequestHeaderField() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Foo")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-    }
-
-    public void testVaryMatchesAddedRequestHeaderField() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Foo")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        URLConnection fooConnection = server.getUrl("/").openConnection();
-        fooConnection.addRequestProperty("Foo", "bar");
-        assertEquals("B", readAscii(fooConnection));
-    }
-
-    public void testVaryMatchesRemovedRequestHeaderField() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Foo")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URLConnection fooConnection = server.getUrl("/").openConnection();
-        fooConnection.addRequestProperty("Foo", "bar");
-        assertEquals("A", readAscii(fooConnection));
-        assertEquals("B", readAscii(server.getUrl("/").openConnection()));
-    }
-
-    public void testVaryFieldsAreCaseInsensitive() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: ACCEPT-LANGUAGE")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection1 = url.openConnection();
-        connection1.addRequestProperty("Accept-Language", "fr-CA");
-        assertEquals("A", readAscii(connection1));
-        URLConnection connection2 = url.openConnection();
-        connection2.addRequestProperty("accept-language", "fr-CA");
-        assertEquals("A", readAscii(connection2));
-    }
-
-    public void testVaryMultipleFieldsWithMatch() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language, Accept-Charset")
-                .addHeader("Vary: Accept-Encoding")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection1 = url.openConnection();
-        connection1.addRequestProperty("Accept-Language", "fr-CA");
-        connection1.addRequestProperty("Accept-Charset", "UTF-8");
-        connection1.addRequestProperty("Accept-Encoding", "identity");
-        assertEquals("A", readAscii(connection1));
-        URLConnection connection2 = url.openConnection();
-        connection2.addRequestProperty("Accept-Language", "fr-CA");
-        connection2.addRequestProperty("Accept-Charset", "UTF-8");
-        connection2.addRequestProperty("Accept-Encoding", "identity");
-        assertEquals("A", readAscii(connection2));
-    }
-
-    public void testVaryMultipleFieldsWithNoMatch() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language, Accept-Charset")
-                .addHeader("Vary: Accept-Encoding")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection frConnection = url.openConnection();
-        frConnection.addRequestProperty("Accept-Language", "fr-CA");
-        frConnection.addRequestProperty("Accept-Charset", "UTF-8");
-        frConnection.addRequestProperty("Accept-Encoding", "identity");
-        assertEquals("A", readAscii(frConnection));
-        URLConnection enConnection = url.openConnection();
-        enConnection.addRequestProperty("Accept-Language", "en-CA");
-        enConnection.addRequestProperty("Accept-Charset", "UTF-8");
-        enConnection.addRequestProperty("Accept-Encoding", "identity");
-        assertEquals("B", readAscii(enConnection));
-    }
-
-    public void testVaryMultipleFieldValuesWithMatch() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection1 = url.openConnection();
-        connection1.addRequestProperty("Accept-Language", "fr-CA, fr-FR");
-        connection1.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("A", readAscii(connection1));
-
-        URLConnection connection2 = url.openConnection();
-        connection2.addRequestProperty("Accept-Language", "fr-CA, fr-FR");
-        connection2.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("A", readAscii(connection2));
-    }
-
-    public void testVaryMultipleFieldValuesWithNoMatch() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection1 = url.openConnection();
-        connection1.addRequestProperty("Accept-Language", "fr-CA, fr-FR");
-        connection1.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("A", readAscii(connection1));
-
-        URLConnection connection2 = url.openConnection();
-        connection2.addRequestProperty("Accept-Language", "fr-CA");
-        connection2.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("B", readAscii(connection2));
-    }
-
-    public void testVaryAsterisk() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: *")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals("B", readAscii(server.getUrl("/").openConnection()));
-    }
-
-    public void testVaryAndHttps() throws Exception {
-        TestSSLContext testSSLContext = TestSSLContext.create();
-        server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        HttpsURLConnection connection1 = (HttpsURLConnection) url.openConnection();
-        connection1.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        connection1.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("A", readAscii(connection1));
-
-        HttpsURLConnection connection2 = (HttpsURLConnection) url.openConnection();
-        connection2.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        connection2.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("A", readAscii(connection2));
-    }
-
-    public void testDiskWriteFailureCacheDegradation() throws Exception {
-        Deque<InvocationHandler> writeHandlers = mockOs.getHandlers("write");
-        int i = 0;
-        boolean hasMoreScenarios = true;
-        while (hasMoreScenarios) {
-            mockOs.enqueueNormal("write", i++);
-            mockOs.enqueueFault("write");
-            exercisePossiblyFaultyCache(false);
-            hasMoreScenarios = writeHandlers.isEmpty();
-            writeHandlers.clear();
-        }
-        System.out.println("Exercising the cache performs " + (i - 1) + " writes.");
-    }
-
-    public void testDiskReadFailureCacheDegradation() throws Exception {
-        Deque<InvocationHandler> readHandlers = mockOs.getHandlers("read");
-        int i = 0;
-        boolean hasMoreScenarios = true;
-        while (hasMoreScenarios) {
-            mockOs.enqueueNormal("read", i++);
-            mockOs.enqueueFault("read");
-            exercisePossiblyFaultyCache(true);
-            hasMoreScenarios = readHandlers.isEmpty();
-            readHandlers.clear();
-        }
-        System.out.println("Exercising the cache performs " + (i - 1) + " reads.");
-    }
-
-    public void testCachePlusCookies() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Set-Cookie: a=FIRST; domain=" + server.getCookieDomain() + ";")
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse()
-                .addHeader("Set-Cookie: a=SECOND; domain=" + server.getCookieDomain() + ";")
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-        assertCookies(url, "a=FIRST");
-        assertEquals("A", readAscii(url.openConnection()));
-        assertCookies(url, "a=SECOND");
-    }
-
-    public void testGetHeadersReturnsNetworkEndToEndHeaders() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Allow: GET, HEAD")
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse()
-                .addHeader("Allow: GET, HEAD, PUT")
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        URLConnection connection1 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection1));
-        assertEquals("GET, HEAD", connection1.getHeaderField("Allow"));
-
-        URLConnection connection2 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection2));
-        assertEquals("GET, HEAD, PUT", connection2.getHeaderField("Allow"));
-    }
-
-    public void testGetHeadersReturnsCachedHopByHopHeaders() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Transfer-Encoding: identity")
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse()
-                .addHeader("Transfer-Encoding: none")
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        URLConnection connection1 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection1));
-        assertEquals("identity", connection1.getHeaderField("Transfer-Encoding"));
-
-        URLConnection connection2 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection2));
-        assertEquals("identity", connection2.getHeaderField("Transfer-Encoding"));
-    }
-
-    public void testGetHeadersDeletesCached100LevelWarnings() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Warning: 199 test danger")
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse()
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        URLConnection connection1 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection1));
-        assertEquals("199 test danger", connection1.getHeaderField("Warning"));
-
-        URLConnection connection2 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection2));
-        assertEquals(null, connection2.getHeaderField("Warning"));
-    }
-
-    public void testGetHeadersRetainsCached200LevelWarnings() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Warning: 299 test danger")
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse()
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        URLConnection connection1 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection1));
-        assertEquals("299 test danger", connection1.getHeaderField("Warning"));
-
-        URLConnection connection2 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection2));
-        assertEquals("299 test danger", connection2.getHeaderField("Warning"));
-    }
-
-    public void assertCookies(URL url, String... expectedCookies) throws Exception {
-        List<String> actualCookies = new ArrayList<String>();
-        for (HttpCookie cookie : cookieManager.getCookieStore().get(url.toURI())) {
-            actualCookies.add(cookie.toString());
-        }
-        assertEquals(Arrays.asList(expectedCookies), actualCookies);
-    }
-
-    public void testCachePlusRange() throws Exception {
-        assertNotCached(new MockResponse()
-                .setResponseCode(HttpURLConnection.HTTP_PARTIAL)
-                .addHeader("Date: " + formatDate(0, TimeUnit.HOURS))
-                .addHeader("Content-Range: bytes 100-100/200")
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testConditionalHitUpdatesCache() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(0, TimeUnit.SECONDS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=30")
-                .addHeader("Allow: GET, HEAD")
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        // cache miss; seed the cache
-        HttpURLConnection connection1 = (HttpURLConnection) server.getUrl("/a").openConnection();
-        assertEquals("A", readAscii(connection1));
-        assertEquals(null, connection1.getHeaderField("Allow"));
-
-        // conditional cache hit; update the cache
-        HttpURLConnection connection2 = (HttpURLConnection) server.getUrl("/a").openConnection();
-        assertEquals(HttpURLConnection.HTTP_OK, connection2.getResponseCode());
-        assertEquals("A", readAscii(connection2));
-        assertEquals("GET, HEAD", connection2.getHeaderField("Allow"));
-
-        // full cache hit
-        HttpURLConnection connection3 = (HttpURLConnection) server.getUrl("/a").openConnection();
-        assertEquals("A", readAscii(connection3));
-        assertEquals("GET, HEAD", connection3.getHeaderField("Allow"));
-
-        assertEquals(2, server.getRequestCount());
-    }
-
-    /**
-     * @param delta the offset from the current date to use. Negative
-     *     values yield dates in the past; positive values yield dates in the
-     *     future.
-     */
-    private String formatDate(long delta, TimeUnit timeUnit) {
-        return formatDate(new Date(System.currentTimeMillis() + timeUnit.toMillis(delta)));
-    }
-
-    private String formatDate(Date date) {
-        DateFormat rfc1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
-        rfc1123.setTimeZone(TimeZone.getTimeZone("UTC"));
-        return rfc1123.format(date);
-    }
-
-    private void addRequestBodyIfNecessary(String requestMethod, HttpURLConnection invalidate)
-            throws IOException {
-        if (requestMethod.equals("POST") || requestMethod.equals("PUT")) {
-            invalidate.setDoOutput(true);
-            OutputStream requestBody = invalidate.getOutputStream();
-            requestBody.write('x');
-            requestBody.close();
-        }
-    }
-
-    private void assertNotCached(MockResponse response) throws Exception {
-        server.enqueue(response.setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-        assertEquals("B", readAscii(url.openConnection()));
-    }
-
-    private void exercisePossiblyFaultyCache(boolean permitReadBodyFailures) throws Exception {
-        server.shutdown();
-        server = new MockWebServer();
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/" + UUID.randomUUID());
-        assertEquals("A", readAscii(url.openConnection()));
-
-        URLConnection connection = url.openConnection();
-        InputStream in = connection.getInputStream();
-        try {
-            int bodyChar = in.read();
-            assertTrue(bodyChar == 'A' || bodyChar == 'B');
-            assertEquals(-1, in.read());
-        } catch (IOException e) {
-            if (!permitReadBodyFailures) {
-                throw e;
-            }
-        }
-    }
-
-    /**
-     * @return the request with the conditional get headers.
-     */
-    private RecordedRequest assertConditionallyCached(MockResponse response) throws Exception {
-        // scenario 1: condition succeeds
-        server.enqueue(response.setBody("A").setStatus("HTTP/1.1 200 A-OK"));
-        server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-
-        // scenario 2: condition fails
-        server.enqueue(response.setBody("B").setStatus("HTTP/1.1 200 B-OK"));
-        server.enqueue(new MockResponse().setStatus("HTTP/1.1 200 C-OK").setBody("C"));
-
-        server.play();
-
-        URL valid = server.getUrl("/valid");
-        HttpURLConnection connection1 = (HttpURLConnection) valid.openConnection();
-        assertEquals("A", readAscii(connection1));
-        assertEquals(HttpURLConnection.HTTP_OK, connection1.getResponseCode());
-        assertEquals("A-OK", connection1.getResponseMessage());
-        HttpURLConnection connection2 = (HttpURLConnection) valid.openConnection();
-        assertEquals("A", readAscii(connection2));
-        assertEquals(HttpURLConnection.HTTP_OK, connection2.getResponseCode());
-        assertEquals("A-OK", connection2.getResponseMessage());
-
-        URL invalid = server.getUrl("/invalid");
-        HttpURLConnection connection3 = (HttpURLConnection) invalid.openConnection();
-        assertEquals("B", readAscii(connection3));
-        assertEquals(HttpURLConnection.HTTP_OK, connection3.getResponseCode());
-        assertEquals("B-OK", connection3.getResponseMessage());
-        HttpURLConnection connection4 = (HttpURLConnection) invalid.openConnection();
-        assertEquals("C", readAscii(connection4));
-        assertEquals(HttpURLConnection.HTTP_OK, connection4.getResponseCode());
-        assertEquals("C-OK", connection4.getResponseMessage());
-
-        server.takeRequest(); // regular get
-        return server.takeRequest(); // conditional get
-    }
-
-    private void assertFullyCached(MockResponse response) throws Exception {
-        server.enqueue(response.setBody("A"));
-        server.enqueue(response.setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-        assertEquals("A", readAscii(url.openConnection()));
-    }
-
-    /**
-     * Shortens the body of {@code response} but not the corresponding headers.
-     * Only useful to test how clients respond to the premature conclusion of
-     * the HTTP body.
-     */
-    private MockResponse truncateViolently(MockResponse response, int numBytesToKeep) {
-        response.setSocketPolicy(DISCONNECT_AT_END);
-        List<String> headers = new ArrayList<String>(response.getHeaders());
-        response.setBody(Arrays.copyOfRange(response.getBody(), 0, numBytesToKeep));
-        response.getHeaders().clear();
-        response.getHeaders().addAll(headers);
-        return response;
-    }
-
-    /**
-     * Reads {@code count} characters from the stream. If the stream is
-     * exhausted before {@code count} characters can be read, the remaining
-     * characters are returned and the stream is closed.
-     */
-    private String readAscii(URLConnection connection, int count) throws IOException {
-        HttpURLConnection httpConnection = (HttpURLConnection) connection;
-        InputStream in = httpConnection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST
-                ? connection.getInputStream()
-                : httpConnection.getErrorStream();
-        StringBuilder result = new StringBuilder();
-        for (int i = 0; i < count; i++) {
-            int value = in.read();
-            if (value == -1) {
-                in.close();
-                break;
-            }
-            result.append((char) value);
-        }
-        return result.toString();
-    }
-
-    private String readAscii(URLConnection connection) throws IOException {
-        return readAscii(connection, Integer.MAX_VALUE);
-    }
-
-    private void reliableSkip(InputStream in, int length) throws IOException {
-        while (length > 0) {
-            length -= in.skip(length);
-        }
-    }
-
-    private void assertGatewayTimeout(HttpURLConnection connection) throws IOException {
-        try {
-            connection.getInputStream();
-            fail();
-        } catch (FileNotFoundException expected) {
-        }
-        assertEquals(504, connection.getResponseCode());
-        assertEquals(-1, connection.getErrorStream().read());
-    }
-
-    enum TransferKind {
-        CHUNKED() {
-            @Override void setBody(MockResponse response, byte[] content, int chunkSize)
-                    throws IOException {
-                response.setChunkedBody(content, chunkSize);
-            }
-        },
-        FIXED_LENGTH() {
-            @Override void setBody(MockResponse response, byte[] content, int chunkSize) {
-                response.setBody(content);
-            }
-        },
-        END_OF_STREAM() {
-            @Override void setBody(MockResponse response, byte[] content, int chunkSize) {
-                response.setBody(content);
-                response.setSocketPolicy(DISCONNECT_AT_END);
-                for (Iterator<String> h = response.getHeaders().iterator(); h.hasNext(); ) {
-                    if (h.next().startsWith("Content-Length:")) {
-                        h.remove();
-                        break;
-                    }
-                }
-            }
-        };
-
-        abstract void setBody(MockResponse response, byte[] content, int chunkSize)
-                throws IOException;
-
-        void setBody(MockResponse response, String content, int chunkSize) throws IOException {
-            setBody(response, content.getBytes("UTF-8"), chunkSize);
-        }
-    }
-
-    private <T> List<T> toListOrNull(T[] arrayOrNull) {
-        return arrayOrNull != null ? Arrays.asList(arrayOrNull) : null;
-    }
-
-    /**
-     * Returns a gzipped copy of {@code bytes}.
-     */
-    public byte[] gzip(byte[] bytes) throws IOException {
-        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
-        OutputStream gzippedOut = new GZIPOutputStream(bytesOut);
-        gzippedOut.write(bytes);
-        gzippedOut.close();
-        return bytesOut.toByteArray();
-    }
-
-    private class InsecureResponseCache extends ResponseCache {
-        @Override public CacheRequest put(URI uri, URLConnection connection) throws IOException {
-            return cache.put(uri, connection);
-        }
-
-        @Override public CacheResponse get(URI uri, String requestMethod,
-                Map<String, List<String>> requestHeaders) throws IOException {
-            final CacheResponse response = cache.get(uri, requestMethod, requestHeaders);
-            if (response instanceof SecureCacheResponse) {
-                return new CacheResponse() {
-                    @Override public InputStream getBody() throws IOException {
-                        return response.getBody();
-                    }
-                    @Override public Map<String, List<String>> getHeaders() throws IOException {
-                        return response.getHeaders();
-                    }
-                };
-            }
-            return response;
-        }
-    }
-}
diff --git a/luni/src/test/java/libcore/net/http/ParsedHeadersTest.java b/luni/src/test/java/libcore/net/http/ParsedHeadersTest.java
deleted file mode 100644
index d7ba441..0000000
--- a/luni/src/test/java/libcore/net/http/ParsedHeadersTest.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
-* Copyright (C) 2011 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-package libcore.net.http;
-
-import java.net.URI;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import junit.framework.TestCase;
-
-public final class ParsedHeadersTest extends TestCase {
-
-    private URI uri;
-
-    @Override protected void setUp() throws Exception {
-        super.setUp();
-        uri = new URI("http", "localhost", "/");
-    }
-
-    public void testUpperCaseHttpHeaders() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("CACHE-CONTROL", "no-store");
-        headers.add("DATE", "Thu, 01 Jan 1970 00:00:01 UTC");
-        headers.add("EXPIRES", "Thu, 01 Jan 1970 00:00:02 UTC");
-        headers.add("LAST-MODIFIED", "Thu, 01 Jan 1970 00:00:03 UTC");
-        headers.add("ETAG", "v1");
-        headers.add("PRAGMA", "no-cache");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoStore());
-        assertEquals(new Date(1000), parsedHeaders.getServedDate());
-        assertEquals(new Date(2000), parsedHeaders.getExpires());
-        assertEquals(new Date(3000), parsedHeaders.getLastModified());
-        assertEquals("v1", parsedHeaders.getEtag());
-        assertTrue(parsedHeaders.isNoCache());
-    }
-
-    public void testCommaSeparatedCacheControlHeaders() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "no-store, max-age=60, public");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoStore());
-        assertEquals(60, parsedHeaders.getMaxAgeSeconds());
-        assertTrue(parsedHeaders.isPublic());
-    }
-
-    public void testQuotedFieldName() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "private=\"Set-Cookie\", no-store");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoStore());
-    }
-
-    public void testUnquotedValue() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "private=Set-Cookie, no-store");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoStore());
-    }
-
-    public void testQuotedValue() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "private=\" a, no-cache, c \", no-store");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoStore());
-        assertFalse(parsedHeaders.isNoCache());
-    }
-
-    public void testDanglingQuote() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "private=\"a, no-cache, c");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertFalse(parsedHeaders.isNoCache());
-    }
-
-    public void testTrailingComma() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "public,");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isPublic());
-    }
-
-    public void testTrailingEquals() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "private=");
-        new ResponseHeaders(uri, headers);
-    }
-
-    public void testSpaceBeforeEquals() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "max-age =60");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertEquals(60, parsedHeaders.getMaxAgeSeconds());
-    }
-
-    public void testSpaceAfterEqualsWithQuotes() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "max-age= \"60\"");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertEquals(60, parsedHeaders.getMaxAgeSeconds());
-    }
-
-    public void testSpaceAfterEqualsWithoutQuotes() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "max-age= 60");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertEquals(60, parsedHeaders.getMaxAgeSeconds());
-    }
-
-    public void testCacheControlRequestDirectivesAreCaseInsensitive() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "NO-CACHE");
-        headers.add("Cache-Control", "MAX-AGE=60");
-        headers.add("Cache-Control", "MAX-STALE=70");
-        headers.add("Cache-Control", "MIN-FRESH=80");
-        headers.add("Cache-Control", "ONLY-IF-CACHED");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoCache());
-        assertEquals(60, parsedHeaders.getMaxAgeSeconds());
-        assertEquals(70, parsedHeaders.getMaxStaleSeconds());
-        assertEquals(80, parsedHeaders.getMinFreshSeconds());
-        assertTrue(parsedHeaders.isOnlyIfCached());
-    }
-
-    public void testCacheControlResponseDirectivesAreCaseInsensitive() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "NO-CACHE");
-        headers.add("Cache-Control", "NO-STORE");
-        headers.add("Cache-Control", "MAX-AGE=60");
-        headers.add("Cache-Control", "S-MAXAGE=70");
-        headers.add("Cache-Control", "PUBLIC");
-        headers.add("Cache-Control", "MUST-REVALIDATE");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoCache());
-        assertTrue(parsedHeaders.isNoStore());
-        assertEquals(60, parsedHeaders.getMaxAgeSeconds());
-        assertEquals(70, parsedHeaders.getSMaxAgeSeconds());
-        assertTrue(parsedHeaders.isPublic());
-        assertTrue(parsedHeaders.isMustRevalidate());
-    }
-
-    public void testPragmaDirectivesAreCaseInsensitive() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Pragma", "NO-CACHE");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoCache());
-    }
-
-    public void testMissingInteger() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "max-age");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertEquals(-1, parsedHeaders.getMaxAgeSeconds());
-    }
-
-    public void testInvalidInteger() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "MAX-AGE=pi");
-        RequestHeaders requestHeaders = new RequestHeaders(uri, headers);
-        assertEquals(-1, requestHeaders.getMaxAgeSeconds());
-    }
-
-    public void testVeryLargeInteger() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "MAX-AGE=" + (Integer.MAX_VALUE + 1L));
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertEquals(Integer.MAX_VALUE, parsedHeaders.getMaxAgeSeconds());
-    }
-
-    public void testNegativeInteger() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "MAX-AGE=-2");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertEquals(0, parsedHeaders.getMaxAgeSeconds());
-    }
-
-    public void testParseChallengesWithCommaInRealm() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "s1 realm=\"ab,cd\", s2 realm=\"ef,gh\"");
-        assertEquals(Arrays.asList(new Challenge("s1", "ab,cd"), new Challenge("s2", "ef,gh")),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-
-    public void testParseChallengesWithMultipleHeaders() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "s1 realm=\"abc\"");
-        headers.add("WWW-Authenticate", "s2 realm=\"def\"");
-        assertEquals(Arrays.asList(new Challenge("s1", "abc"), new Challenge("s2", "def")),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-
-    public void testParseChallengesWithExtraWhitespace() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "  s1  realm=\"a\"  ,  s2  realm=\"b\",  ");
-        assertEquals(Arrays.asList(new Challenge("s1", "a"), new Challenge("s2", "b")),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-
-    public void testParseChallengesWithMissingRealm() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "Basic");
-        assertEquals(Collections.<Challenge>emptyList(),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-
-    public void testParseChallengesWithEmptyRealm() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "Basic realm=\"\"");
-        assertEquals(Arrays.asList(new Challenge("Basic", "")),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-
-    public void testParseChallengesWithMissingScheme() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "realm=\"a\"");
-        assertEquals(Collections.<Challenge>emptyList(),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-
-    // http://code.google.com/p/android/issues/detail?id=11140
-    public void testParseChallengesWithManyParameters() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "Digest realm=\"abc\","
-                + " qop=\"auth,auth-int\","
-                + " nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\","
-                + " opaque=\"5ccc069c403ebaf9f0171e9517f40e41\","
-                + " Basic realm=\"def\"");
-        assertEquals(Arrays.asList(new Challenge("Digest", "abc"), new Challenge("Basic", "def")),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-}
diff --git a/luni/src/test/java/libcore/net/http/RawHeadersTest.java b/luni/src/test/java/libcore/net/http/RawHeadersTest.java
deleted file mode 100644
index d99e851..0000000
--- a/luni/src/test/java/libcore/net/http/RawHeadersTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.util.Arrays;
-import junit.framework.TestCase;
-
-public class RawHeadersTest extends TestCase {
-    // http://code.google.com/p/android/issues/detail?id=6684
-    public void test_caseInsensitiveButCasePreserving() {
-        RawHeaders h = new RawHeaders();
-        h.add("Content-Type", "text/plain");
-        // Case-insensitive:
-        assertEquals("text/plain", h.get("Content-Type"));
-        assertEquals("text/plain", h.get("Content-type"));
-        assertEquals("text/plain", h.get("content-type"));
-        assertEquals("text/plain", h.get("CONTENT-TYPE"));
-        // ...but case-preserving:
-        assertEquals("Content-Type", h.toMultimap().keySet().toArray()[0]);
-
-        // We differ from the RI in that the Map we return is also case-insensitive.
-        // Our behavior seems more consistent. (And code that works on the RI will work on Android.)
-        assertEquals(Arrays.asList("text/plain"), h.toMultimap().get("Content-Type"));
-        assertEquals(Arrays.asList("text/plain"), h.toMultimap().get("Content-type")); // RI fails this.
-    }
-
-    // The copy constructor used to be broken for headers with multiple values.
-    // http://code.google.com/p/android/issues/detail?id=6722
-    public void test_copyConstructor() {
-        RawHeaders h1 = new RawHeaders();
-        h1.add("key", "value1");
-        h1.add("key", "value2");
-        RawHeaders h2 = RawHeaders.fromMultimap(h1.toMultimap());
-        assertEquals(2, h2.length());
-        assertEquals("key", h2.getFieldName(0));
-        assertEquals("value1", h2.getValue(0));
-        assertEquals("key", h2.getFieldName(1));
-        assertEquals("value2", h2.getValue(1));
-    }
-}