18bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller/*
28bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *  Licensed to the Apache Software Foundation (ASF) under one or more
38bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *  contributor license agreements.  See the NOTICE file distributed with
48bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *  this work for additional information regarding copyright ownership.
58bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *  The ASF licenses this file to You under the Apache License, Version 2.0
68bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *  (the "License"); you may not use this file except in compliance with
78bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *  the License.  You may obtain a copy of the License at
88bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *
98bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *     http://www.apache.org/licenses/LICENSE-2.0
108bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *
118bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *  Unless required by applicable law or agreed to in writing, software
128bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *  distributed under the License is distributed on an "AS IS" BASIS,
138bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
148bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *  See the License for the specific language governing permissions and
158bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller *  limitations under the License.
168bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller */
178bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller
188bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fullerpackage com.squareup.okhttp;
198bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller
208bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fullerimport libcore.net.event.NetworkEventDispatcher;
218bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fullerimport libcore.net.event.NetworkEventListener;
228bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller
238bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller/**
248bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller * A provider of the shared Android {@link ConnectionPool}. This class is aware of network
258bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller * configuration change events: When the network configuration changes the pool object is discarded
268bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller * and a later calls to {@link #get()} will return a new pool.
278bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller */
288bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fullerpublic class ConfigAwareConnectionPool {
298bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller
308bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  private static final long CONNECTION_POOL_DEFAULT_KEEP_ALIVE_DURATION_MS = 5 * 60 * 1000; // 5 min
318bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller
328bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  private static final int CONNECTION_POOL_MAX_IDLE_CONNECTIONS;
338bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  private static final long CONNECTION_POOL_KEEP_ALIVE_DURATION_MS;
348bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  static {
358bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    String keepAliveProperty = System.getProperty("http.keepAlive");
368bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    String keepAliveDurationProperty = System.getProperty("http.keepAliveDuration");
378bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    String maxIdleConnectionsProperty = System.getProperty("http.maxConnections");
388bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    CONNECTION_POOL_KEEP_ALIVE_DURATION_MS = (keepAliveDurationProperty != null
398bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller        ? Long.parseLong(keepAliveDurationProperty)
408bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller        : CONNECTION_POOL_DEFAULT_KEEP_ALIVE_DURATION_MS);
418bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    if (keepAliveProperty != null && !Boolean.parseBoolean(keepAliveProperty)) {
428bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller      CONNECTION_POOL_MAX_IDLE_CONNECTIONS = 0;
438bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    } else if (maxIdleConnectionsProperty != null) {
448bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller      CONNECTION_POOL_MAX_IDLE_CONNECTIONS = Integer.parseInt(maxIdleConnectionsProperty);
458bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    } else {
468bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller      CONNECTION_POOL_MAX_IDLE_CONNECTIONS = 5;
478bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    }
488bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  }
498bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller
508bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  private static final ConfigAwareConnectionPool instance = new ConfigAwareConnectionPool();
518bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller
528bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  private final NetworkEventDispatcher networkEventDispatcher;
538bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller
548bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  /**
558bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller   * {@code true} if the ConnectionPool reset has been registered with the
568bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller   * {@link NetworkEventDispatcher}.
578bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller   */
588bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  private boolean networkEventListenerRegistered;
598bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller
608bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  private ConnectionPool connectionPool;
618bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller
628bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  /** Visible for testing. Use {@link #getInstance()} */
638bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  protected ConfigAwareConnectionPool(NetworkEventDispatcher networkEventDispatcher) {
648bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    this.networkEventDispatcher = networkEventDispatcher;
658bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  }
668bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller
678bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  private ConfigAwareConnectionPool() {
688bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    networkEventDispatcher = NetworkEventDispatcher.getInstance();
698bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  }
708bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller
718bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  public static ConfigAwareConnectionPool getInstance() {
728bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    return instance;
738bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  }
748bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller
758bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  /**
768bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller   * Returns the current {@link ConnectionPool} to use.
778bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller   */
788bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  public synchronized ConnectionPool get() {
798bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    if (connectionPool == null) {
808bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller      // Only register the listener once the first time a ConnectionPool is created.
818bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller      if (!networkEventListenerRegistered) {
828bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller        networkEventDispatcher.addListener(new NetworkEventListener() {
838bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller          @Override
848bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller          public void onNetworkConfigurationChanged() {
858bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller            synchronized (ConfigAwareConnectionPool.this) {
868bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller              // If the network config has changed then existing pooled connections should not be
878bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller              // re-used. By setting connectionPool to null it ensures that the next time
888bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller              // getConnectionPool() is called a new pool will be created.
898bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller              connectionPool = null;
908bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller            }
918bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller          }
928bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller        });
938bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller        networkEventListenerRegistered = true;
948bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller      }
958bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller      connectionPool = new ConnectionPool(
968bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller          CONNECTION_POOL_MAX_IDLE_CONNECTIONS, CONNECTION_POOL_KEEP_ALIVE_DURATION_MS);
978bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    }
988bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller    return connectionPool;
998bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller  }
1008bced3e769d315a0a81b89de7a5282f1a85acbf7Neil Fuller}
101