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 java.lang.Thread;
23
24class ConnectionThread extends Thread {
25
26    static final int WAIT_TIMEOUT = 5000;
27    static final int WAIT_TICK = 1000;
28
29    // Performance probe
30    long mCurrentThreadTime;
31    long mTotalThreadTime;
32
33    private boolean mWaiting;
34    private volatile boolean mRunning = true;
35    private Context mContext;
36    private RequestQueue.ConnectionManager mConnectionManager;
37    private RequestFeeder mRequestFeeder;
38
39    private int mId;
40    Connection mConnection;
41
42    ConnectionThread(Context context,
43                     int id,
44                     RequestQueue.ConnectionManager connectionManager,
45                     RequestFeeder requestFeeder) {
46        super();
47        mContext = context;
48        setName("http" + id);
49        mId = id;
50        mConnectionManager = connectionManager;
51        mRequestFeeder = requestFeeder;
52    }
53
54    void requestStop() {
55        synchronized (mRequestFeeder) {
56            mRunning = false;
57            mRequestFeeder.notify();
58        }
59    }
60
61    /**
62     * Loop until app shutdown. Runs connections in priority
63     * order.
64     */
65    public void run() {
66        android.os.Process.setThreadPriority(
67                android.os.Process.THREAD_PRIORITY_DEFAULT +
68                android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
69
70        // these are used to get performance data. When it is not in the timing,
71        // mCurrentThreadTime is 0. When it starts timing, mCurrentThreadTime is
72        // first set to -1, it will be set to the current thread time when the
73        // next request starts.
74        mCurrentThreadTime = 0;
75        mTotalThreadTime = 0;
76
77        while (mRunning) {
78            if (mCurrentThreadTime == -1) {
79                mCurrentThreadTime = SystemClock.currentThreadTimeMillis();
80            }
81
82            Request request;
83
84            /* Get a request to process */
85            request = mRequestFeeder.getRequest();
86
87            /* wait for work */
88            if (request == null) {
89                synchronized(mRequestFeeder) {
90                    if (HttpLog.LOGV) HttpLog.v("ConnectionThread: Waiting for work");
91                    mWaiting = true;
92                    try {
93                        mRequestFeeder.wait();
94                    } catch (InterruptedException e) {
95                    }
96                    mWaiting = false;
97                    if (mCurrentThreadTime != 0) {
98                        mCurrentThreadTime = SystemClock
99                                .currentThreadTimeMillis();
100                    }
101                }
102            } else {
103                if (HttpLog.LOGV) HttpLog.v("ConnectionThread: new request " +
104                                            request.mHost + " " + request );
105
106                mConnection = mConnectionManager.getConnection(mContext,
107                        request.mHost);
108                mConnection.processRequests(request);
109                if (mConnection.getCanPersist()) {
110                    if (!mConnectionManager.recycleConnection(mConnection)) {
111                        mConnection.closeConnection();
112                    }
113                } else {
114                    mConnection.closeConnection();
115                }
116                mConnection = null;
117
118                if (mCurrentThreadTime > 0) {
119                    long start = mCurrentThreadTime;
120                    mCurrentThreadTime = SystemClock.currentThreadTimeMillis();
121                    mTotalThreadTime += mCurrentThreadTime - start;
122                }
123            }
124
125        }
126    }
127
128    public synchronized String toString() {
129        String con = mConnection == null ? "" : mConnection.toString();
130        String active = mWaiting ? "w" : "a";
131        return "cid " + mId + " " + active + " "  + con;
132    }
133
134}
135