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