1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net.http;
18
19import android.content.Context;
20import android.os.SystemClock;
21
22import org.apache.http.HttpHost;
23
24import java.lang.Thread;
25
26/**
27 * {@hide}
28 */
29class ConnectionThread extends Thread {
30
31    static final int WAIT_TIMEOUT = 5000;
32    static final int WAIT_TICK = 1000;
33
34    // Performance probe
35    long mCurrentThreadTime;
36    long mTotalThreadTime;
37
38    private boolean mWaiting;
39    private volatile boolean mRunning = true;
40    private Context mContext;
41    private RequestQueue.ConnectionManager mConnectionManager;
42    private RequestFeeder mRequestFeeder;
43
44    private int mId;
45    Connection mConnection;
46
47    ConnectionThread(Context context,
48                     int id,
49                     RequestQueue.ConnectionManager connectionManager,
50                     RequestFeeder requestFeeder) {
51        super();
52        mContext = context;
53        setName("http" + id);
54        mId = id;
55        mConnectionManager = connectionManager;
56        mRequestFeeder = requestFeeder;
57    }
58
59    void requestStop() {
60        synchronized (mRequestFeeder) {
61            mRunning = false;
62            mRequestFeeder.notify();
63        }
64    }
65
66    /**
67     * Loop until app shutdown. Runs connections in priority
68     * order.
69     */
70    public void run() {
71        android.os.Process.setThreadPriority(
72                android.os.Process.THREAD_PRIORITY_DEFAULT +
73                android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
74
75        // these are used to get performance data. When it is not in the timing,
76        // mCurrentThreadTime is 0. When it starts timing, mCurrentThreadTime is
77        // first set to -1, it will be set to the current thread time when the
78        // next request starts.
79        mCurrentThreadTime = 0;
80        mTotalThreadTime = 0;
81
82        while (mRunning) {
83            if (mCurrentThreadTime == -1) {
84                mCurrentThreadTime = SystemClock.currentThreadTimeMillis();
85            }
86
87            Request request;
88
89            /* Get a request to process */
90            request = mRequestFeeder.getRequest();
91
92            /* wait for work */
93            if (request == null) {
94                synchronized(mRequestFeeder) {
95                    if (HttpLog.LOGV) HttpLog.v("ConnectionThread: Waiting for work");
96                    mWaiting = true;
97                    try {
98                        mRequestFeeder.wait();
99                    } catch (InterruptedException e) {
100                    }
101                    mWaiting = false;
102                    if (mCurrentThreadTime != 0) {
103                        mCurrentThreadTime = SystemClock
104                                .currentThreadTimeMillis();
105                    }
106                }
107            } else {
108                if (HttpLog.LOGV) HttpLog.v("ConnectionThread: new request " +
109                                            request.mHost + " " + request );
110
111                mConnection = mConnectionManager.getConnection(mContext,
112                        request.mHost);
113                mConnection.processRequests(request);
114                if (mConnection.getCanPersist()) {
115                    if (!mConnectionManager.recycleConnection(mConnection)) {
116                        mConnection.closeConnection();
117                    }
118                } else {
119                    mConnection.closeConnection();
120                }
121                mConnection = null;
122
123                if (mCurrentThreadTime > 0) {
124                    long start = mCurrentThreadTime;
125                    mCurrentThreadTime = SystemClock.currentThreadTimeMillis();
126                    mTotalThreadTime += mCurrentThreadTime - start;
127                }
128            }
129
130        }
131    }
132
133    public synchronized String toString() {
134        String con = mConnection == null ? "" : mConnection.toString();
135        String active = mWaiting ? "w" : "a";
136        return "cid " + mId + " " + active + " "  + con;
137    }
138
139}
140