Merge "Create a full facade over okhttp"
am: a588b1faeb

Change-Id: I19667f54934fa8d2889b5ddac994a4215547e9b0
diff --git a/android/main/java/com/android/okhttp/internalandroidapi/AndroidResponseCacheAdapter.java b/android/main/java/com/android/okhttp/internalandroidapi/AndroidResponseCacheAdapter.java
new file mode 100644
index 0000000..57b2c6a
--- /dev/null
+++ b/android/main/java/com/android/okhttp/internalandroidapi/AndroidResponseCacheAdapter.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2015 Square, Inc.
+ *
+ * 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 com.android.okhttp.internalandroidapi;
+
+import com.android.okhttp.internalandroidapi.HasCacheHolder.CacheHolder;
+import com.squareup.okhttp.Cache;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.Response;
+import com.squareup.okhttp.internal.huc.JavaApiConverter;
+
+import java.io.IOException;
+import java.net.CacheRequest;
+import java.net.CacheResponse;
+import java.net.URI;
+import java.net.URLConnection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A modified copy of {@link com.squareup.okhttp.AndroidShimResponseCache} that exposes a
+ * {@link CacheHolder} instead of a {@link Cache}. We want to keep the framework code that interacts
+ * with OkHttp at arms length. By delegating to this class the Android HttpResponseCache class has
+ * no knowledge of OkHttp internal classes at class resolution time and there are no internal
+ * classes appearing on method signatures.
+ */
+public final class AndroidResponseCacheAdapter {
+
+    private final CacheHolder cacheHolder;
+    private final Cache okHttpCache;
+
+    public AndroidResponseCacheAdapter(CacheHolder cacheHolder) {
+        this.cacheHolder = cacheHolder;
+        // Avoid one level of dereferencing by storing the reference to the OkHttp cache for later.
+        this.okHttpCache = cacheHolder.getCache();
+    }
+
+    /**
+     * Returns the {@link CacheHolder} associated with this instance and can be used by OkHttp
+     * internal code to obtain the underlying OkHttp Cache object.
+     * @hide
+     */
+    public CacheHolder getCacheHolder() {
+        return cacheHolder;
+    }
+
+    /**
+     * Used to implement {@link java.net.ResponseCache#get(URI, String, Map)}. See that method for
+     * details.
+     */
+    public CacheResponse get(URI uri, String requestMethod,
+            Map<String, List<String>> requestHeaders) throws IOException {
+        Request okRequest = JavaApiConverter.createOkRequest(uri, requestMethod, requestHeaders);
+        Response okResponse = okHttpCache.internalCache.get(okRequest);
+        if (okResponse == null) {
+            return null;
+        }
+        return JavaApiConverter.createJavaCacheResponse(okResponse);
+    }
+
+    /**
+     * Used to implement {@link java.net.ResponseCache#put(URI, URLConnection)}. See that method for
+     * details.
+     */
+    public CacheRequest put(URI uri, URLConnection urlConnection) throws IOException {
+        Response okResponse = JavaApiConverter.createOkResponseForCachePut(uri, urlConnection);
+        if (okResponse == null) {
+            // The URLConnection is not cacheable or could not be converted. Stop.
+            return null;
+        }
+        com.squareup.okhttp.internal.http.CacheRequest okCacheRequest =
+                okHttpCache.internalCache.put(okResponse);
+        if (okCacheRequest == null) {
+            return null;
+        }
+        return JavaApiConverter.createJavaCacheRequest(okCacheRequest);
+    }
+
+    /**
+     * Returns the number of bytes currently being used to store the values in
+     * this cache. This may be greater than the {@link #getMaxSize()} if a background
+     * deletion is pending. IOException is thrown if the size cannot be determined.
+     */
+    public long getSize() throws IOException {
+        return okHttpCache.getSize();
+    }
+
+    /**
+     * Returns the maximum number of bytes that this cache should use to store
+     * its data.
+     */
+    public long getMaxSize() {
+        return okHttpCache.getMaxSize();
+    }
+
+    /**
+     * Force buffered operations to the filesystem. This ensures that responses
+     * written to the cache will be available the next time the cache is opened,
+     * even if this process is killed. IOException is thrown if the flush fails.
+     */
+    public void flush() throws IOException {
+        okHttpCache.flush();
+    }
+
+    /**
+     * Returns the number of HTTP requests that required the network to either
+     * supply a response or validate a locally cached response.
+     */
+    public int getNetworkCount() {
+        return okHttpCache.getNetworkCount();
+    }
+
+    /**
+     * Returns the number of HTTP requests whose response was provided by the
+     * cache. This may include conditional {@code GET} requests that were
+     * validated over the network.
+     */
+    public int getHitCount() {
+        return okHttpCache.getHitCount();
+    }
+
+    /**
+     * Returns the total number of HTTP requests that were made. This includes
+     * both client requests and requests that were made on the client's behalf
+     * to handle a redirects and retries.
+     */
+    public int getRequestCount() {
+        return okHttpCache.getRequestCount();
+    }
+
+    /** Closes this cache. Stored values will remain on the filesystem. */
+    public void close() throws IOException {
+        okHttpCache.close();
+    }
+
+    /**
+     * Closes the cache and deletes all of its stored values. This will delete
+     * all files in the cache directory including files that weren't created by
+     * the cache.
+     */
+    public void delete() throws IOException {
+        okHttpCache.delete();
+    }
+}
diff --git a/android/main/java/com/squareup/okhttp/internalandroidapi/Dns.java b/android/main/java/com/android/okhttp/internalandroidapi/Dns.java
similarity index 95%
rename from android/main/java/com/squareup/okhttp/internalandroidapi/Dns.java
rename to android/main/java/com/android/okhttp/internalandroidapi/Dns.java
index 349fade..5486d28 100644
--- a/android/main/java/com/squareup/okhttp/internalandroidapi/Dns.java
+++ b/android/main/java/com/android/okhttp/internalandroidapi/Dns.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.squareup.okhttp.internalandroidapi;
+package com.android.okhttp.internalandroidapi;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
diff --git a/android/main/java/com/android/okhttp/internalandroidapi/HasCacheHolder.java b/android/main/java/com/android/okhttp/internalandroidapi/HasCacheHolder.java
new file mode 100644
index 0000000..c32d83a
--- /dev/null
+++ b/android/main/java/com/android/okhttp/internalandroidapi/HasCacheHolder.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 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 com.android.okhttp.internalandroidapi;
+
+import com.squareup.okhttp.Cache;
+
+import java.io.File;
+
+/**
+ * An interface used to indicate a class can return a {@link CacheHolder} object.
+ */
+public interface HasCacheHolder {
+
+    /**
+     * Returns the {@link CacheHolder} object.
+     */
+    CacheHolder getCacheHolder();
+
+    /**
+     * A holder for an OkHttp internal Cache object. This class exists as an opaque layer over
+     * OkHttp internal classes.
+     */
+    final class CacheHolder {
+
+        private final Cache okHttpCache;
+
+        private CacheHolder(Cache okHttpCache) {
+            this.okHttpCache = okHttpCache;
+        }
+
+        /**
+         * Returns the underlying {@link Cache} object.
+         * @hide
+         */
+        public Cache getCache() {
+            return okHttpCache;
+        }
+
+        /**
+         * Returns a new {@link CacheHolder} containing an OKHttp Cache with the specified settings.
+         *
+         * @param directory a writable directory
+         * @param maxSizeBytes the maximum number of bytes this cache should use to store
+         */
+        public static CacheHolder create(File directory, long maxSizeBytes) {
+            Cache cache = new Cache(directory, maxSizeBytes);
+            return new CacheHolder(cache);
+        }
+
+        /**
+         * Returns true if the arguments supplied would result in an equivalent cache to this one
+         * being created if they were passed to {@link #create(File, long)}.
+         */
+        public boolean isEquivalent(File directory, long maxSizeBytes) {
+            return (okHttpCache.getDirectory().equals(directory)
+                    && okHttpCache.getMaxSize() == maxSizeBytes
+                    && !okHttpCache.isClosed());
+        }
+    }
+}
diff --git a/android/main/java/com/squareup/okhttp/internalandroidapi/HttpURLConnectionFactory.java b/android/main/java/com/android/okhttp/internalandroidapi/HttpURLConnectionFactory.java
similarity index 97%
rename from android/main/java/com/squareup/okhttp/internalandroidapi/HttpURLConnectionFactory.java
rename to android/main/java/com/android/okhttp/internalandroidapi/HttpURLConnectionFactory.java
index f1da451..bd585c7 100644
--- a/android/main/java/com/squareup/okhttp/internalandroidapi/HttpURLConnectionFactory.java
+++ b/android/main/java/com/android/okhttp/internalandroidapi/HttpURLConnectionFactory.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.squareup.okhttp.internalandroidapi;
+package com.android.okhttp.internalandroidapi;
 
 import com.squareup.okhttp.ConnectionPool;
 import com.squareup.okhttp.HttpHandler;
@@ -38,7 +38,7 @@
 /**
  * A way to construct {@link java.net.HttpURLConnection}s that supports some
  * configuration on a per-factory or per-connection basis rather than only via
- * global static state such as {@link CookieHandler#setDefault(CookieHandler)}.
+ * global static state such as {@link java.net.CookieHandler#setDefault(java.net.CookieHandler)}.
  * The per-factory configuration is <b>optional</b>; if not set, global
  * configuration or default behavior is used.
  *
diff --git a/android/main/java/com/android/okhttp/internalandroidapi/README b/android/main/java/com/android/okhttp/internalandroidapi/README
new file mode 100644
index 0000000..f9f79e8
--- /dev/null
+++ b/android/main/java/com/android/okhttp/internalandroidapi/README
@@ -0,0 +1,4 @@
+This package contains a facade over OkHttp that some parts of Android framework are allowed to
+depend on.
+
+Please talk to the maintainers before adding any new dependencies.
diff --git a/android/main/java/com/squareup/okhttp/internalandroidapi/README b/android/main/java/com/squareup/okhttp/internalandroidapi/README
deleted file mode 100644
index e332837..0000000
--- a/android/main/java/com/squareup/okhttp/internalandroidapi/README
+++ /dev/null
@@ -1,5 +0,0 @@
-This package contains a facade over OkHttp that some parts of Android framework are allowed to
-depend on. This is not a stable API; it is an attempt to decouple framework code from OkHttp as
-much as is practical where public APIs cannot be used.
-
-Please talk to the maintainers before adding any new dependencies.
diff --git a/okhttp-android-support/src/main/java/com/squareup/okhttp/AndroidInternal.java b/okhttp-android-support/src/main/java/com/squareup/okhttp/AndroidInternal.java
index eeaf554..739ac34 100644
--- a/okhttp-android-support/src/main/java/com/squareup/okhttp/AndroidInternal.java
+++ b/okhttp-android-support/src/main/java/com/squareup/okhttp/AndroidInternal.java
@@ -15,6 +15,8 @@
  */
 package com.squareup.okhttp;
 
+import com.android.okhttp.internalandroidapi.HasCacheHolder;
+import com.android.okhttp.internalandroidapi.HasCacheHolder.CacheHolder;
 import com.squareup.okhttp.internal.huc.CacheAdapter;
 
 import java.net.ResponseCache;
@@ -38,6 +40,15 @@
       // This means that Cache stats will be correctly updated.
       OkCacheContainer okCacheContainer = (OkCacheContainer) responseCache;
       client.setCache(okCacheContainer.getCache());
+    // BEGIN Android-added: Recognize internalapi.HasCacheHolder.
+    } else if (responseCache instanceof HasCacheHolder) {
+      // Avoid adding layers of wrappers. Rather than wrap the ResponseCache in yet another layer to
+      // make the ResponseCache look like an InternalCache using CacheAdapter, we can unwrap the
+      // held Cache instead. This means that Cache stats will be correctly updated by OkHttp.
+      HasCacheHolder hasCacheHolder = (HasCacheHolder) responseCache;
+      CacheHolder cacheHolder = hasCacheHolder.getCacheHolder();
+      client.setCache(cacheHolder.getCache());
+    // END Android-added: Recognize internalapi.HasCacheHolder.
     } else {
       client.setInternalCache(responseCache != null ? new CacheAdapter(responseCache) : null);
     }
diff --git a/okhttp/src/main/java/com/squareup/okhttp/Cache.java b/okhttp/src/main/java/com/squareup/okhttp/Cache.java
index dcf3634..024d035 100644
--- a/okhttp/src/main/java/com/squareup/okhttp/Cache.java
+++ b/okhttp/src/main/java/com/squareup/okhttp/Cache.java
@@ -134,7 +134,8 @@
   private static final int ENTRY_BODY = 1;
   private static final int ENTRY_COUNT = 2;
 
-  final InternalCache internalCache = new InternalCache() {
+  // Android-changed: internalCache made public so it can be used from Android internalapi package.
+  public final InternalCache internalCache = new InternalCache() {
     @Override public Response get(Request request) throws IOException {
       return Cache.this.get(request);
     }