1/*
2 * Copyright (C) 2011 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
17//#define LOG_NDEBUG 0
18#define LOG_TAG "HTTPBase"
19#include <utils/Log.h>
20
21#include "include/HTTPBase.h"
22
23#if CHROMIUM_AVAILABLE
24#include "include/chromium_http_stub.h"
25#endif
26
27#include <media/stagefright/foundation/ADebug.h>
28#include <media/stagefright/foundation/ALooper.h>
29
30#include <cutils/properties.h>
31#include <cutils/qtaguid.h>
32
33#include <ConnectivityManager.h>
34
35namespace android {
36
37HTTPBase::HTTPBase()
38    : mNumBandwidthHistoryItems(0),
39      mTotalTransferTimeUs(0),
40      mTotalTransferBytes(0),
41      mPrevBandwidthMeasureTimeUs(0),
42      mPrevEstimatedBandWidthKbps(0),
43      mBandWidthCollectFreqMs(5000),
44      mUIDValid(false),
45      mUID(0) {
46}
47
48// static
49sp<HTTPBase> HTTPBase::Create(uint32_t flags) {
50#if CHROMIUM_AVAILABLE
51        HTTPBase *dataSource = createChromiumHTTPDataSource(flags);
52        if (dataSource) {
53           return dataSource;
54        }
55#endif
56    {
57        TRESPASS();
58
59        return NULL;
60    }
61}
62
63// static
64status_t HTTPBase::UpdateProxyConfig(
65        const char *host, int32_t port, const char *exclusionList) {
66#if CHROMIUM_AVAILABLE
67    return UpdateChromiumHTTPDataSourceProxyConfig(host, port, exclusionList);
68#else
69    return INVALID_OPERATION;
70#endif
71}
72
73void HTTPBase::addBandwidthMeasurement(
74        size_t numBytes, int64_t delayUs) {
75    Mutex::Autolock autoLock(mLock);
76
77    BandwidthEntry entry;
78    entry.mDelayUs = delayUs;
79    entry.mNumBytes = numBytes;
80    mTotalTransferTimeUs += delayUs;
81    mTotalTransferBytes += numBytes;
82
83    mBandwidthHistory.push_back(entry);
84    if (++mNumBandwidthHistoryItems > 100) {
85        BandwidthEntry *entry = &*mBandwidthHistory.begin();
86        mTotalTransferTimeUs -= entry->mDelayUs;
87        mTotalTransferBytes -= entry->mNumBytes;
88        mBandwidthHistory.erase(mBandwidthHistory.begin());
89        --mNumBandwidthHistoryItems;
90
91        int64_t timeNowUs = ALooper::GetNowUs();
92        if (timeNowUs - mPrevBandwidthMeasureTimeUs >=
93                mBandWidthCollectFreqMs * 1000LL) {
94
95            if (mPrevBandwidthMeasureTimeUs != 0) {
96                mPrevEstimatedBandWidthKbps =
97                    (mTotalTransferBytes * 8E3 / mTotalTransferTimeUs);
98            }
99            mPrevBandwidthMeasureTimeUs = timeNowUs;
100        }
101    }
102
103}
104
105bool HTTPBase::estimateBandwidth(int32_t *bandwidth_bps) {
106    Mutex::Autolock autoLock(mLock);
107
108    if (mNumBandwidthHistoryItems < 2) {
109        return false;
110    }
111
112    *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
113
114    return true;
115}
116
117status_t HTTPBase::getEstimatedBandwidthKbps(int32_t *kbps) {
118    Mutex::Autolock autoLock(mLock);
119    *kbps = mPrevEstimatedBandWidthKbps;
120    return OK;
121}
122
123status_t HTTPBase::setBandwidthStatCollectFreq(int32_t freqMs) {
124    Mutex::Autolock autoLock(mLock);
125
126    if (freqMs < kMinBandwidthCollectFreqMs
127            || freqMs > kMaxBandwidthCollectFreqMs) {
128
129        ALOGE("frequency (%d ms) is out of range [1000, 60000]", freqMs);
130        return BAD_VALUE;
131    }
132
133    ALOGI("frequency set to %d ms", freqMs);
134    mBandWidthCollectFreqMs = freqMs;
135    return OK;
136}
137
138void HTTPBase::setUID(uid_t uid) {
139    mUIDValid = true;
140    mUID = uid;
141}
142
143bool HTTPBase::getUID(uid_t *uid) const {
144    if (!mUIDValid) {
145        return false;
146    }
147
148    *uid = mUID;
149
150    return true;
151}
152
153// static
154void HTTPBase::RegisterSocketUserTag(int sockfd, uid_t uid, uint32_t kTag) {
155    int res = qtaguid_tagSocket(sockfd, kTag, uid);
156    if (res != 0) {
157        ALOGE("Failed tagging socket %d for uid %d (My UID=%d)", sockfd, uid, geteuid());
158    }
159}
160
161// static
162void HTTPBase::UnRegisterSocketUserTag(int sockfd) {
163    int res = qtaguid_untagSocket(sockfd);
164    if (res != 0) {
165        ALOGE("Failed untagging socket %d (My UID=%d)", sockfd, geteuid());
166    }
167}
168
169// static
170void HTTPBase::RegisterSocketUserMark(int sockfd, uid_t uid) {
171    ConnectivityManager::markSocketAsUser(sockfd, uid);
172}
173
174// static
175void HTTPBase::UnRegisterSocketUserMark(int sockfd) {
176    RegisterSocketUserMark(sockfd, geteuid());
177}
178
179}  // namespace android
180