11b86fe063badb5f28c467ade39be0f4008688947Andreas Huber/*
21b86fe063badb5f28c467ade39be0f4008688947Andreas Huber * Copyright (C) 2013 The Android Open Source Project
31b86fe063badb5f28c467ade39be0f4008688947Andreas Huber *
41b86fe063badb5f28c467ade39be0f4008688947Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
51b86fe063badb5f28c467ade39be0f4008688947Andreas Huber * you may not use this file except in compliance with the License.
61b86fe063badb5f28c467ade39be0f4008688947Andreas Huber * You may obtain a copy of the License at
71b86fe063badb5f28c467ade39be0f4008688947Andreas Huber *
81b86fe063badb5f28c467ade39be0f4008688947Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
91b86fe063badb5f28c467ade39be0f4008688947Andreas Huber *
101b86fe063badb5f28c467ade39be0f4008688947Andreas Huber * Unless required by applicable law or agreed to in writing, software
111b86fe063badb5f28c467ade39be0f4008688947Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
121b86fe063badb5f28c467ade39be0f4008688947Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131b86fe063badb5f28c467ade39be0f4008688947Andreas Huber * See the License for the specific language governing permissions and
141b86fe063badb5f28c467ade39be0f4008688947Andreas Huber * limitations under the License.
151b86fe063badb5f28c467ade39be0f4008688947Andreas Huber */
161b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
171b86fe063badb5f28c467ade39be0f4008688947Andreas Huber//#define LOG_NDEBUG 0
181b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#define LOG_TAG "MediaHTTP"
191b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <utils/Log.h>
201b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
211b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/stagefright/MediaHTTP.h>
221b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
231b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <binder/IServiceManager.h>
241b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/stagefright/foundation/ADebug.h>
251b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/stagefright/foundation/ALooper.h>
261b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/stagefright/Utils.h>
271b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
281b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPConnection.h>
291b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
301b86fe063badb5f28c467ade39be0f4008688947Andreas Hubernamespace android {
311b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
321b86fe063badb5f28c467ade39be0f4008688947Andreas HuberMediaHTTP::MediaHTTP(const sp<IMediaHTTPConnection> &conn)
3337d8b27e5470d8243288a87e90871efd43f29606Chong Zhang    : mInitCheck((conn != NULL) ? OK : NO_INIT),
341b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPConnection(conn),
351b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mCachedSizeValid(false),
361b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mCachedSize(0ll),
371b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mDrmManagerClient(NULL) {
381b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
391b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
401b86fe063badb5f28c467ade39be0f4008688947Andreas HuberMediaHTTP::~MediaHTTP() {
411b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    clearDRMState_l();
421b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
431b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
441b86fe063badb5f28c467ade39be0f4008688947Andreas Huberstatus_t MediaHTTP::connect(
451b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const char *uri,
461b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const KeyedVector<String8, String8> *headers,
471b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        off64_t /* offset */) {
481b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mInitCheck != OK) {
491b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return mInitCheck;
501b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
511b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
521b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    KeyedVector<String8, String8> extHeaders;
531b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (headers != NULL) {
541b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        extHeaders = *headers;
551b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
56b074c3ce4dd157b656e4e8c66bc228ee2a1be5dbMarco Nelissen
57b074c3ce4dd157b656e4e8c66bc228ee2a1be5dbMarco Nelissen    if (extHeaders.indexOfKey(String8("User-Agent")) < 0) {
58b074c3ce4dd157b656e4e8c66bc228ee2a1be5dbMarco Nelissen        extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str()));
59b074c3ce4dd157b656e4e8c66bc228ee2a1be5dbMarco Nelissen    }
601b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
611b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    bool success = mHTTPConnection->connect(uri, &extHeaders);
621b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
631b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    mLastHeaders = extHeaders;
641b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    mLastURI = uri;
651b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
661b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    mCachedSizeValid = false;
671b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
6869d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen    if (success) {
6969d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen        AString sanitized = uriDebugString(uri);
7069d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen        mName = String8::format("MediaHTTP(%s)", sanitized.c_str());
7169d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen    }
7269d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen
731b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return success ? OK : UNKNOWN_ERROR;
741b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
751b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
761b86fe063badb5f28c467ade39be0f4008688947Andreas Hubervoid MediaHTTP::disconnect() {
7769d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen    mName = String8("MediaHTTP(<disconnected>)");
781b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mInitCheck != OK) {
791b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return;
801b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
811b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
821b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    mHTTPConnection->disconnect();
831b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
841b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
851b86fe063badb5f28c467ade39be0f4008688947Andreas Huberstatus_t MediaHTTP::initCheck() const {
861b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return mInitCheck;
871b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
881b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
891b86fe063badb5f28c467ade39be0f4008688947Andreas Huberssize_t MediaHTTP::readAt(off64_t offset, void *data, size_t size) {
901b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mInitCheck != OK) {
911b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return mInitCheck;
921b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
931b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
941b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    int64_t startTimeUs = ALooper::GetNowUs();
951b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
961b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    size_t numBytesRead = 0;
971b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    while (numBytesRead < size) {
981b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        size_t copy = size - numBytesRead;
991b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1001b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        if (copy > 64 * 1024) {
1011b86fe063badb5f28c467ade39be0f4008688947Andreas Huber            // limit the buffer sizes transferred across binder boundaries
1021b86fe063badb5f28c467ade39be0f4008688947Andreas Huber            // to avoid spurious transaction failures.
1031b86fe063badb5f28c467ade39be0f4008688947Andreas Huber            copy = 64 * 1024;
1041b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        }
1051b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1061b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        ssize_t n = mHTTPConnection->readAt(
1071b86fe063badb5f28c467ade39be0f4008688947Andreas Huber                offset + numBytesRead, (uint8_t *)data + numBytesRead, copy);
1081b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1091b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        if (n < 0) {
1101b86fe063badb5f28c467ade39be0f4008688947Andreas Huber            return n;
1111b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        } else if (n == 0) {
1121b86fe063badb5f28c467ade39be0f4008688947Andreas Huber            break;
1131b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        }
1141b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1151b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        numBytesRead += n;
1161b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1171b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1181b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
1191b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1201b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    addBandwidthMeasurement(numBytesRead, delayUs);
1211b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1221b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return numBytesRead;
1231b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1241b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1251b86fe063badb5f28c467ade39be0f4008688947Andreas Huberstatus_t MediaHTTP::getSize(off64_t *size) {
1261b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mInitCheck != OK) {
1271b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return mInitCheck;
1281b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1291b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1301b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    // Caching the returned size so that it stays valid even after a
1311b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    // disconnect. NuCachedSource2 relies on this.
1321b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1331b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (!mCachedSizeValid) {
1341b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mCachedSize = mHTTPConnection->getSize();
1351b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mCachedSizeValid = true;
1361b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1371b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1381b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    *size = mCachedSize;
1391b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
140b3f9759c8c9437c45b9a34519ce2ea38a8314d4eAndreas Gampe    return *size < 0 ? *size : static_cast<status_t>(OK);
1411b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1421b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1431b86fe063badb5f28c467ade39be0f4008688947Andreas Huberuint32_t MediaHTTP::flags() {
1441b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return kWantsPrefetching | kIsHTTPBasedSource;
1451b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1461b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1471b86fe063badb5f28c467ade39be0f4008688947Andreas Huberstatus_t MediaHTTP::reconnectAtOffset(off64_t offset) {
1481b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return connect(mLastURI.c_str(), &mLastHeaders, offset);
1491b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1501b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1511b86fe063badb5f28c467ade39be0f4008688947Andreas Huber// DRM...
1521b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1531b86fe063badb5f28c467ade39be0f4008688947Andreas Hubersp<DecryptHandle> MediaHTTP::DrmInitialization(const char* mime) {
1541b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mDrmManagerClient == NULL) {
1551b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mDrmManagerClient = new DrmManagerClient();
1561b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1571b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1581b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mDrmManagerClient == NULL) {
1591b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return NULL;
1601b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1611b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1621b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mDecryptHandle == NULL) {
1631b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mDecryptHandle = mDrmManagerClient->openDecryptSession(
1641b86fe063badb5f28c467ade39be0f4008688947Andreas Huber                String8(mLastURI.c_str()), mime);
1651b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1661b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1671b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mDecryptHandle == NULL) {
1681b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        delete mDrmManagerClient;
1691b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mDrmManagerClient = NULL;
1701b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1711b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1721b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return mDecryptHandle;
1731b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1741b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1751b86fe063badb5f28c467ade39be0f4008688947Andreas Hubervoid MediaHTTP::getDrmInfo(
1761b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        sp<DecryptHandle> &handle, DrmManagerClient **client) {
1771b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    handle = mDecryptHandle;
1781b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    *client = mDrmManagerClient;
1791b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1801b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1811b86fe063badb5f28c467ade39be0f4008688947Andreas HuberString8 MediaHTTP::getUri() {
18237d8b27e5470d8243288a87e90871efd43f29606Chong Zhang    if (mInitCheck != OK) {
18337d8b27e5470d8243288a87e90871efd43f29606Chong Zhang        return String8::empty();
18437d8b27e5470d8243288a87e90871efd43f29606Chong Zhang    }
18537d8b27e5470d8243288a87e90871efd43f29606Chong Zhang
186c9c7e25a4b1c34439fb365f6cfbef063884566ccMarco Nelissen    String8 uri;
187c9c7e25a4b1c34439fb365f6cfbef063884566ccMarco Nelissen    if (OK == mHTTPConnection->getUri(&uri)) {
188c9c7e25a4b1c34439fb365f6cfbef063884566ccMarco Nelissen        return uri;
189c9c7e25a4b1c34439fb365f6cfbef063884566ccMarco Nelissen    }
1901b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return String8(mLastURI.c_str());
1911b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1921b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1931b86fe063badb5f28c467ade39be0f4008688947Andreas HuberString8 MediaHTTP::getMIMEType() const {
1941b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mInitCheck != OK) {
1951b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return String8("application/octet-stream");
1961b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1971b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1981b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    String8 mimeType;
1991b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    status_t err = mHTTPConnection->getMIMEType(&mimeType);
2001b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
2011b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (err != OK) {
2021b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return String8("application/octet-stream");
2031b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
2041b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
2051b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return mimeType;
2061b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
2071b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
2081b86fe063badb5f28c467ade39be0f4008688947Andreas Hubervoid MediaHTTP::clearDRMState_l() {
2091b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mDecryptHandle != NULL) {
2101b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        // To release mDecryptHandle
2111b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        CHECK(mDrmManagerClient);
2121b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
2131b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mDecryptHandle = NULL;
2141b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
2151b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
2161b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
2171b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}  // namespace android
218