Home | History | Annotate | Download | only in okhttp
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package com.squareup.okhttp;
     19 
     20 import libcore.net.event.NetworkEventDispatcher;
     21 import libcore.net.event.NetworkEventListener;
     22 
     23 /**
     24  * A provider of the shared Android {@link ConnectionPool}. This class is aware of network
     25  * configuration change events: When the network configuration changes the pool object is discarded
     26  * and a later calls to {@link #get()} will return a new pool.
     27  */
     28 public class ConfigAwareConnectionPool {
     29 
     30   private static final long CONNECTION_POOL_DEFAULT_KEEP_ALIVE_DURATION_MS = 5 * 60 * 1000; // 5 min
     31 
     32   private static final int CONNECTION_POOL_MAX_IDLE_CONNECTIONS;
     33   private static final long CONNECTION_POOL_KEEP_ALIVE_DURATION_MS;
     34   static {
     35     String keepAliveProperty = System.getProperty("http.keepAlive");
     36     String keepAliveDurationProperty = System.getProperty("http.keepAliveDuration");
     37     String maxIdleConnectionsProperty = System.getProperty("http.maxConnections");
     38     CONNECTION_POOL_KEEP_ALIVE_DURATION_MS = (keepAliveDurationProperty != null
     39         ? Long.parseLong(keepAliveDurationProperty)
     40         : CONNECTION_POOL_DEFAULT_KEEP_ALIVE_DURATION_MS);
     41     if (keepAliveProperty != null && !Boolean.parseBoolean(keepAliveProperty)) {
     42       CONNECTION_POOL_MAX_IDLE_CONNECTIONS = 0;
     43     } else if (maxIdleConnectionsProperty != null) {
     44       CONNECTION_POOL_MAX_IDLE_CONNECTIONS = Integer.parseInt(maxIdleConnectionsProperty);
     45     } else {
     46       CONNECTION_POOL_MAX_IDLE_CONNECTIONS = 5;
     47     }
     48   }
     49 
     50   private static final ConfigAwareConnectionPool instance = new ConfigAwareConnectionPool();
     51 
     52   private final NetworkEventDispatcher networkEventDispatcher;
     53 
     54   /**
     55    * {@code true} if the ConnectionPool reset has been registered with the
     56    * {@link NetworkEventDispatcher}.
     57    */
     58   private boolean networkEventListenerRegistered;
     59 
     60   private ConnectionPool connectionPool;
     61 
     62   /** Visible for testing. Use {@link #getInstance()} */
     63   protected ConfigAwareConnectionPool(NetworkEventDispatcher networkEventDispatcher) {
     64     this.networkEventDispatcher = networkEventDispatcher;
     65   }
     66 
     67   private ConfigAwareConnectionPool() {
     68     networkEventDispatcher = NetworkEventDispatcher.getInstance();
     69   }
     70 
     71   public static ConfigAwareConnectionPool getInstance() {
     72     return instance;
     73   }
     74 
     75   /**
     76    * Returns the current {@link ConnectionPool} to use.
     77    */
     78   public synchronized ConnectionPool get() {
     79     if (connectionPool == null) {
     80       // Only register the listener once the first time a ConnectionPool is created.
     81       if (!networkEventListenerRegistered) {
     82         networkEventDispatcher.addListener(new NetworkEventListener() {
     83           @Override
     84           public void onNetworkConfigurationChanged() {
     85             synchronized (ConfigAwareConnectionPool.this) {
     86               // If the network config has changed then existing pooled connections should not be
     87               // re-used. By setting connectionPool to null it ensures that the next time
     88               // getConnectionPool() is called a new pool will be created.
     89               connectionPool = null;
     90             }
     91           }
     92         });
     93         networkEventListenerRegistered = true;
     94       }
     95       connectionPool = new ConnectionPool(
     96           CONNECTION_POOL_MAX_IDLE_CONNECTIONS, CONNECTION_POOL_KEEP_ALIVE_DURATION_MS);
     97     }
     98     return connectionPool;
     99   }
    100 }
    101