1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "MediaHTTP"
19*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
20*ec779b8eSAndroid Build Coastguard Worker
21*ec779b8eSAndroid Build Coastguard Worker #include <datasource/MediaHTTP.h>
22*ec779b8eSAndroid Build Coastguard Worker
23*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ALooper.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/FoundationUtils.h>
26*ec779b8eSAndroid Build Coastguard Worker
27*ec779b8eSAndroid Build Coastguard Worker #include <media/MediaHTTPConnection.h>
28*ec779b8eSAndroid Build Coastguard Worker
29*ec779b8eSAndroid Build Coastguard Worker namespace android {
30*ec779b8eSAndroid Build Coastguard Worker
MediaHTTP(const sp<MediaHTTPConnection> & conn)31*ec779b8eSAndroid Build Coastguard Worker MediaHTTP::MediaHTTP(const sp<MediaHTTPConnection> &conn)
32*ec779b8eSAndroid Build Coastguard Worker : mInitCheck((conn != NULL) ? OK : NO_INIT),
33*ec779b8eSAndroid Build Coastguard Worker mHTTPConnection(conn),
34*ec779b8eSAndroid Build Coastguard Worker mCachedSizeValid(false),
35*ec779b8eSAndroid Build Coastguard Worker mCachedSize(0ll) {
36*ec779b8eSAndroid Build Coastguard Worker }
37*ec779b8eSAndroid Build Coastguard Worker
~MediaHTTP()38*ec779b8eSAndroid Build Coastguard Worker MediaHTTP::~MediaHTTP() {
39*ec779b8eSAndroid Build Coastguard Worker }
40*ec779b8eSAndroid Build Coastguard Worker
connect(const char * uri,const KeyedVector<String8,String8> * headers,off64_t)41*ec779b8eSAndroid Build Coastguard Worker status_t MediaHTTP::connect(
42*ec779b8eSAndroid Build Coastguard Worker const char *uri,
43*ec779b8eSAndroid Build Coastguard Worker const KeyedVector<String8, String8> *headers,
44*ec779b8eSAndroid Build Coastguard Worker off64_t /* offset */) {
45*ec779b8eSAndroid Build Coastguard Worker if (mInitCheck != OK) {
46*ec779b8eSAndroid Build Coastguard Worker return mInitCheck;
47*ec779b8eSAndroid Build Coastguard Worker }
48*ec779b8eSAndroid Build Coastguard Worker
49*ec779b8eSAndroid Build Coastguard Worker KeyedVector<String8, String8> extHeaders;
50*ec779b8eSAndroid Build Coastguard Worker if (headers != NULL) {
51*ec779b8eSAndroid Build Coastguard Worker extHeaders = *headers;
52*ec779b8eSAndroid Build Coastguard Worker }
53*ec779b8eSAndroid Build Coastguard Worker
54*ec779b8eSAndroid Build Coastguard Worker if (extHeaders.indexOfKey(String8("User-Agent")) < 0) {
55*ec779b8eSAndroid Build Coastguard Worker extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str()));
56*ec779b8eSAndroid Build Coastguard Worker }
57*ec779b8eSAndroid Build Coastguard Worker
58*ec779b8eSAndroid Build Coastguard Worker mLastURI = uri;
59*ec779b8eSAndroid Build Coastguard Worker // reconnect() calls with uri == old mLastURI.c_str(), which gets zapped
60*ec779b8eSAndroid Build Coastguard Worker // as part of the above assignment. Ensure no accidental later use.
61*ec779b8eSAndroid Build Coastguard Worker uri = NULL;
62*ec779b8eSAndroid Build Coastguard Worker
63*ec779b8eSAndroid Build Coastguard Worker bool success = mHTTPConnection->connect(mLastURI.c_str(), &extHeaders);
64*ec779b8eSAndroid Build Coastguard Worker
65*ec779b8eSAndroid Build Coastguard Worker mLastHeaders = extHeaders;
66*ec779b8eSAndroid Build Coastguard Worker
67*ec779b8eSAndroid Build Coastguard Worker mCachedSizeValid = false;
68*ec779b8eSAndroid Build Coastguard Worker
69*ec779b8eSAndroid Build Coastguard Worker if (success) {
70*ec779b8eSAndroid Build Coastguard Worker AString sanitized = uriDebugString(mLastURI);
71*ec779b8eSAndroid Build Coastguard Worker mName = String8::format("MediaHTTP(%s)", sanitized.c_str());
72*ec779b8eSAndroid Build Coastguard Worker }
73*ec779b8eSAndroid Build Coastguard Worker
74*ec779b8eSAndroid Build Coastguard Worker return success ? OK : UNKNOWN_ERROR;
75*ec779b8eSAndroid Build Coastguard Worker }
76*ec779b8eSAndroid Build Coastguard Worker
close()77*ec779b8eSAndroid Build Coastguard Worker void MediaHTTP::close() {
78*ec779b8eSAndroid Build Coastguard Worker disconnect();
79*ec779b8eSAndroid Build Coastguard Worker }
80*ec779b8eSAndroid Build Coastguard Worker
disconnect()81*ec779b8eSAndroid Build Coastguard Worker void MediaHTTP::disconnect() {
82*ec779b8eSAndroid Build Coastguard Worker mName = String8("MediaHTTP(<disconnected>)");
83*ec779b8eSAndroid Build Coastguard Worker if (mInitCheck != OK) {
84*ec779b8eSAndroid Build Coastguard Worker return;
85*ec779b8eSAndroid Build Coastguard Worker }
86*ec779b8eSAndroid Build Coastguard Worker
87*ec779b8eSAndroid Build Coastguard Worker mHTTPConnection->disconnect();
88*ec779b8eSAndroid Build Coastguard Worker }
89*ec779b8eSAndroid Build Coastguard Worker
initCheck() const90*ec779b8eSAndroid Build Coastguard Worker status_t MediaHTTP::initCheck() const {
91*ec779b8eSAndroid Build Coastguard Worker return mInitCheck;
92*ec779b8eSAndroid Build Coastguard Worker }
93*ec779b8eSAndroid Build Coastguard Worker
readAt(off64_t offset,void * data,size_t size)94*ec779b8eSAndroid Build Coastguard Worker ssize_t MediaHTTP::readAt(off64_t offset, void *data, size_t size) {
95*ec779b8eSAndroid Build Coastguard Worker if (mInitCheck != OK) {
96*ec779b8eSAndroid Build Coastguard Worker return mInitCheck;
97*ec779b8eSAndroid Build Coastguard Worker }
98*ec779b8eSAndroid Build Coastguard Worker
99*ec779b8eSAndroid Build Coastguard Worker int64_t startTimeUs = ALooper::GetNowUs();
100*ec779b8eSAndroid Build Coastguard Worker
101*ec779b8eSAndroid Build Coastguard Worker size_t numBytesRead = 0;
102*ec779b8eSAndroid Build Coastguard Worker while (numBytesRead < size) {
103*ec779b8eSAndroid Build Coastguard Worker size_t copy = size - numBytesRead;
104*ec779b8eSAndroid Build Coastguard Worker
105*ec779b8eSAndroid Build Coastguard Worker if (copy > 64 * 1024) {
106*ec779b8eSAndroid Build Coastguard Worker // limit the buffer sizes transferred across binder boundaries
107*ec779b8eSAndroid Build Coastguard Worker // to avoid spurious transaction failures.
108*ec779b8eSAndroid Build Coastguard Worker copy = 64 * 1024;
109*ec779b8eSAndroid Build Coastguard Worker }
110*ec779b8eSAndroid Build Coastguard Worker
111*ec779b8eSAndroid Build Coastguard Worker ssize_t n = mHTTPConnection->readAt(
112*ec779b8eSAndroid Build Coastguard Worker offset + numBytesRead, (uint8_t *)data + numBytesRead, copy);
113*ec779b8eSAndroid Build Coastguard Worker
114*ec779b8eSAndroid Build Coastguard Worker if (n < 0) {
115*ec779b8eSAndroid Build Coastguard Worker return n;
116*ec779b8eSAndroid Build Coastguard Worker } else if (n == 0) {
117*ec779b8eSAndroid Build Coastguard Worker break;
118*ec779b8eSAndroid Build Coastguard Worker }
119*ec779b8eSAndroid Build Coastguard Worker
120*ec779b8eSAndroid Build Coastguard Worker numBytesRead += n;
121*ec779b8eSAndroid Build Coastguard Worker }
122*ec779b8eSAndroid Build Coastguard Worker
123*ec779b8eSAndroid Build Coastguard Worker int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
124*ec779b8eSAndroid Build Coastguard Worker
125*ec779b8eSAndroid Build Coastguard Worker addBandwidthMeasurement(numBytesRead, delayUs);
126*ec779b8eSAndroid Build Coastguard Worker
127*ec779b8eSAndroid Build Coastguard Worker return numBytesRead;
128*ec779b8eSAndroid Build Coastguard Worker }
129*ec779b8eSAndroid Build Coastguard Worker
getSize(off64_t * size)130*ec779b8eSAndroid Build Coastguard Worker status_t MediaHTTP::getSize(off64_t *size) {
131*ec779b8eSAndroid Build Coastguard Worker if (mInitCheck != OK) {
132*ec779b8eSAndroid Build Coastguard Worker return mInitCheck;
133*ec779b8eSAndroid Build Coastguard Worker }
134*ec779b8eSAndroid Build Coastguard Worker
135*ec779b8eSAndroid Build Coastguard Worker // Caching the returned size so that it stays valid even after a
136*ec779b8eSAndroid Build Coastguard Worker // disconnect. NuCachedSource2 relies on this.
137*ec779b8eSAndroid Build Coastguard Worker
138*ec779b8eSAndroid Build Coastguard Worker if (!mCachedSizeValid) {
139*ec779b8eSAndroid Build Coastguard Worker mCachedSize = mHTTPConnection->getSize();
140*ec779b8eSAndroid Build Coastguard Worker mCachedSizeValid = true;
141*ec779b8eSAndroid Build Coastguard Worker }
142*ec779b8eSAndroid Build Coastguard Worker
143*ec779b8eSAndroid Build Coastguard Worker *size = mCachedSize;
144*ec779b8eSAndroid Build Coastguard Worker
145*ec779b8eSAndroid Build Coastguard Worker return *size < 0 ? *size : static_cast<status_t>(OK);
146*ec779b8eSAndroid Build Coastguard Worker }
147*ec779b8eSAndroid Build Coastguard Worker
flags()148*ec779b8eSAndroid Build Coastguard Worker uint32_t MediaHTTP::flags() {
149*ec779b8eSAndroid Build Coastguard Worker return kWantsPrefetching | kIsHTTPBasedSource;
150*ec779b8eSAndroid Build Coastguard Worker }
151*ec779b8eSAndroid Build Coastguard Worker
reconnectAtOffset(off64_t offset)152*ec779b8eSAndroid Build Coastguard Worker status_t MediaHTTP::reconnectAtOffset(off64_t offset) {
153*ec779b8eSAndroid Build Coastguard Worker return connect(mLastURI.c_str(), &mLastHeaders, offset);
154*ec779b8eSAndroid Build Coastguard Worker }
155*ec779b8eSAndroid Build Coastguard Worker
156*ec779b8eSAndroid Build Coastguard Worker
getUri()157*ec779b8eSAndroid Build Coastguard Worker String8 MediaHTTP::getUri() {
158*ec779b8eSAndroid Build Coastguard Worker if (mInitCheck != OK) {
159*ec779b8eSAndroid Build Coastguard Worker return String8();
160*ec779b8eSAndroid Build Coastguard Worker }
161*ec779b8eSAndroid Build Coastguard Worker
162*ec779b8eSAndroid Build Coastguard Worker String8 uri;
163*ec779b8eSAndroid Build Coastguard Worker if (OK == mHTTPConnection->getUri(&uri)) {
164*ec779b8eSAndroid Build Coastguard Worker return uri;
165*ec779b8eSAndroid Build Coastguard Worker }
166*ec779b8eSAndroid Build Coastguard Worker return String8(mLastURI.c_str());
167*ec779b8eSAndroid Build Coastguard Worker }
168*ec779b8eSAndroid Build Coastguard Worker
getMIMEType() const169*ec779b8eSAndroid Build Coastguard Worker String8 MediaHTTP::getMIMEType() const {
170*ec779b8eSAndroid Build Coastguard Worker if (mInitCheck != OK) {
171*ec779b8eSAndroid Build Coastguard Worker return String8("application/octet-stream");
172*ec779b8eSAndroid Build Coastguard Worker }
173*ec779b8eSAndroid Build Coastguard Worker
174*ec779b8eSAndroid Build Coastguard Worker String8 mimeType;
175*ec779b8eSAndroid Build Coastguard Worker status_t err = mHTTPConnection->getMIMEType(&mimeType);
176*ec779b8eSAndroid Build Coastguard Worker
177*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
178*ec779b8eSAndroid Build Coastguard Worker return String8("application/octet-stream");
179*ec779b8eSAndroid Build Coastguard Worker }
180*ec779b8eSAndroid Build Coastguard Worker
181*ec779b8eSAndroid Build Coastguard Worker return mimeType;
182*ec779b8eSAndroid Build Coastguard Worker }
183*ec779b8eSAndroid Build Coastguard Worker
184*ec779b8eSAndroid Build Coastguard Worker } // namespace android
185