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 #include <media/stagefright/foundation/ADebug.h>
24 #include <media/stagefright/foundation/ALooper.h>
25 
26 #include <cutils/properties.h>
27 #include <cutils/qtaguid.h>
28 
29 #include <NetdClient.h>
30 
31 namespace android {
32 
HTTPBase()33 HTTPBase::HTTPBase()
34     : mNumBandwidthHistoryItems(0),
35       mTotalTransferTimeUs(0),
36       mTotalTransferBytes(0),
37       mMaxBandwidthHistoryItems(100),
38       mPrevBandwidthMeasureTimeUs(0),
39       mPrevEstimatedBandWidthKbps(0),
40       mBandWidthCollectFreqMs(5000) {
41 }
42 
addBandwidthMeasurement(size_t numBytes,int64_t delayUs)43 void HTTPBase::addBandwidthMeasurement(
44         size_t numBytes, int64_t delayUs) {
45     Mutex::Autolock autoLock(mLock);
46 
47     BandwidthEntry entry;
48     entry.mDelayUs = delayUs;
49     entry.mNumBytes = numBytes;
50     mTotalTransferTimeUs += delayUs;
51     mTotalTransferBytes += numBytes;
52 
53     mBandwidthHistory.push_back(entry);
54     if (++mNumBandwidthHistoryItems > mMaxBandwidthHistoryItems) {
55         BandwidthEntry *entry = &*mBandwidthHistory.begin();
56         mTotalTransferTimeUs -= entry->mDelayUs;
57         mTotalTransferBytes -= entry->mNumBytes;
58         mBandwidthHistory.erase(mBandwidthHistory.begin());
59         --mNumBandwidthHistoryItems;
60 
61         int64_t timeNowUs = ALooper::GetNowUs();
62         if (timeNowUs - mPrevBandwidthMeasureTimeUs >=
63                 mBandWidthCollectFreqMs * 1000LL) {
64 
65             if (mPrevBandwidthMeasureTimeUs != 0) {
66                 mPrevEstimatedBandWidthKbps =
67                     (mTotalTransferBytes * 8E3 / mTotalTransferTimeUs);
68             }
69             mPrevBandwidthMeasureTimeUs = timeNowUs;
70         }
71     }
72 
73 }
74 
estimateBandwidth(int32_t * bandwidth_bps)75 bool HTTPBase::estimateBandwidth(int32_t *bandwidth_bps) {
76     Mutex::Autolock autoLock(mLock);
77 
78     // Do not do bandwidth estimation if we don't have enough samples, or
79     // total bytes download are too small (<64K).
80     // Bandwidth estimation from these samples can often shoot up and cause
81     // unwanted bw adaption behaviors.
82     if (mNumBandwidthHistoryItems < 2 || mTotalTransferBytes < 65536) {
83         return false;
84     }
85 
86     *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);
87 
88     return true;
89 }
90 
getEstimatedBandwidthKbps(int32_t * kbps)91 status_t HTTPBase::getEstimatedBandwidthKbps(int32_t *kbps) {
92     Mutex::Autolock autoLock(mLock);
93     *kbps = mPrevEstimatedBandWidthKbps;
94     return OK;
95 }
96 
setBandwidthStatCollectFreq(int32_t freqMs)97 status_t HTTPBase::setBandwidthStatCollectFreq(int32_t freqMs) {
98     Mutex::Autolock autoLock(mLock);
99 
100     if (freqMs < kMinBandwidthCollectFreqMs
101             || freqMs > kMaxBandwidthCollectFreqMs) {
102 
103         ALOGE("frequency (%d ms) is out of range [1000, 60000]", freqMs);
104         return BAD_VALUE;
105     }
106 
107     ALOGI("frequency set to %d ms", freqMs);
108     mBandWidthCollectFreqMs = freqMs;
109     return OK;
110 }
111 
setBandwidthHistorySize(size_t numHistoryItems)112 void HTTPBase::setBandwidthHistorySize(size_t numHistoryItems) {
113     mMaxBandwidthHistoryItems = numHistoryItems;
114 }
115 
116 // static
RegisterSocketUserTag(int sockfd,uid_t uid,uint32_t kTag)117 void HTTPBase::RegisterSocketUserTag(int sockfd, uid_t uid, uint32_t kTag) {
118     int res = qtaguid_tagSocket(sockfd, kTag, uid);
119     if (res != 0) {
120         ALOGE("Failed tagging socket %d for uid %d (My UID=%d)", sockfd, uid, geteuid());
121     }
122 }
123 
124 // static
UnRegisterSocketUserTag(int sockfd)125 void HTTPBase::UnRegisterSocketUserTag(int sockfd) {
126     int res = qtaguid_untagSocket(sockfd);
127     if (res != 0) {
128         ALOGE("Failed untagging socket %d (My UID=%d)", sockfd, geteuid());
129     }
130 }
131 
132 // static
RegisterSocketUserMark(int sockfd,uid_t uid)133 void HTTPBase::RegisterSocketUserMark(int sockfd, uid_t uid) {
134     setNetworkForUser(uid, sockfd);
135 }
136 
137 // static
UnRegisterSocketUserMark(int sockfd)138 void HTTPBase::UnRegisterSocketUserMark(int sockfd) {
139     RegisterSocketUserMark(sockfd, geteuid());
140 }
141 
142 }  // namespace android
143