/* * 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 com.squareup.okhttp; import libcore.net.event.NetworkEventDispatcher; import libcore.net.event.NetworkEventListener; /** * A provider of the shared Android {@link ConnectionPool}. This class is aware of network * configuration change events: When the network configuration changes the pool object is discarded * and a later calls to {@link #get()} will return a new pool. */ public class ConfigAwareConnectionPool { private static final long CONNECTION_POOL_DEFAULT_KEEP_ALIVE_DURATION_MS = 5 * 60 * 1000; // 5 min private static final int CONNECTION_POOL_MAX_IDLE_CONNECTIONS; private static final long CONNECTION_POOL_KEEP_ALIVE_DURATION_MS; static { String keepAliveProperty = System.getProperty("http.keepAlive"); String keepAliveDurationProperty = System.getProperty("http.keepAliveDuration"); String maxIdleConnectionsProperty = System.getProperty("http.maxConnections"); CONNECTION_POOL_KEEP_ALIVE_DURATION_MS = (keepAliveDurationProperty != null ? Long.parseLong(keepAliveDurationProperty) : CONNECTION_POOL_DEFAULT_KEEP_ALIVE_DURATION_MS); if (keepAliveProperty != null && !Boolean.parseBoolean(keepAliveProperty)) { CONNECTION_POOL_MAX_IDLE_CONNECTIONS = 0; } else if (maxIdleConnectionsProperty != null) { CONNECTION_POOL_MAX_IDLE_CONNECTIONS = Integer.parseInt(maxIdleConnectionsProperty); } else { CONNECTION_POOL_MAX_IDLE_CONNECTIONS = 5; } } private static final ConfigAwareConnectionPool instance = new ConfigAwareConnectionPool(); private final NetworkEventDispatcher networkEventDispatcher; /** * {@code true} if the ConnectionPool reset has been registered with the * {@link NetworkEventDispatcher}. */ private boolean networkEventListenerRegistered; private ConnectionPool connectionPool; /** Visible for testing. Use {@link #getInstance()} */ protected ConfigAwareConnectionPool(NetworkEventDispatcher networkEventDispatcher) { this.networkEventDispatcher = networkEventDispatcher; } private ConfigAwareConnectionPool() { networkEventDispatcher = NetworkEventDispatcher.getInstance(); } public static ConfigAwareConnectionPool getInstance() { return instance; } /** * Returns the current {@link ConnectionPool} to use. */ public synchronized ConnectionPool get() { if (connectionPool == null) { // Only register the listener once the first time a ConnectionPool is created. if (!networkEventListenerRegistered) { networkEventDispatcher.addListener(new NetworkEventListener() { @Override public void onNetworkConfigurationChanged() { synchronized (ConfigAwareConnectionPool.this) { // If the network config has changed then existing pooled connections should not be // re-used. By setting connectionPool to null it ensures that the next time // getConnectionPool() is called a new pool will be created. connectionPool = null; } } }); networkEventListenerRegistered = true; } connectionPool = new ConnectionPool( CONNECTION_POOL_MAX_IDLE_CONNECTIONS, CONNECTION_POOL_KEEP_ALIVE_DURATION_MS); } return connectionPool; } }