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)
331b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    : mInitCheck(NO_INIT),
341b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mHTTPConnection(conn),
351b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mCachedSizeValid(false),
361b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mCachedSize(0ll),
371b86fe063badb5f28c467ade39be0f4008688947Andreas Huber      mDrmManagerClient(NULL) {
381b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    mInitCheck = OK;
391b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
401b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
411b86fe063badb5f28c467ade39be0f4008688947Andreas HuberMediaHTTP::~MediaHTTP() {
421b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    clearDRMState_l();
431b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
441b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
451b86fe063badb5f28c467ade39be0f4008688947Andreas Huberstatus_t MediaHTTP::connect(
461b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const char *uri,
471b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        const KeyedVector<String8, String8> *headers,
481b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        off64_t /* offset */) {
491b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mInitCheck != OK) {
501b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return mInitCheck;
511b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
521b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
531b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    KeyedVector<String8, String8> extHeaders;
541b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (headers != NULL) {
551b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        extHeaders = *headers;
561b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
571b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str()));
581b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
591b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    bool success = mHTTPConnection->connect(uri, &extHeaders);
601b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
611b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    mLastHeaders = extHeaders;
621b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    mLastURI = uri;
631b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
641b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    mCachedSizeValid = false;
651b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
661b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return success ? OK : UNKNOWN_ERROR;
671b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
681b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
691b86fe063badb5f28c467ade39be0f4008688947Andreas Hubervoid MediaHTTP::disconnect() {
701b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mInitCheck != OK) {
711b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return;
721b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
731b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
741b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    mHTTPConnection->disconnect();
751b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
761b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
771b86fe063badb5f28c467ade39be0f4008688947Andreas Huberstatus_t MediaHTTP::initCheck() const {
781b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return mInitCheck;
791b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
801b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
811b86fe063badb5f28c467ade39be0f4008688947Andreas Huberssize_t MediaHTTP::readAt(off64_t offset, void *data, size_t size) {
821b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mInitCheck != OK) {
831b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return mInitCheck;
841b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
851b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
861b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    int64_t startTimeUs = ALooper::GetNowUs();
871b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
881b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    size_t numBytesRead = 0;
891b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    while (numBytesRead < size) {
901b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        size_t copy = size - numBytesRead;
911b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
921b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        if (copy > 64 * 1024) {
931b86fe063badb5f28c467ade39be0f4008688947Andreas Huber            // limit the buffer sizes transferred across binder boundaries
941b86fe063badb5f28c467ade39be0f4008688947Andreas Huber            // to avoid spurious transaction failures.
951b86fe063badb5f28c467ade39be0f4008688947Andreas Huber            copy = 64 * 1024;
961b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        }
971b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
981b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        ssize_t n = mHTTPConnection->readAt(
991b86fe063badb5f28c467ade39be0f4008688947Andreas Huber                offset + numBytesRead, (uint8_t *)data + numBytesRead, copy);
1001b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1011b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        if (n < 0) {
1021b86fe063badb5f28c467ade39be0f4008688947Andreas Huber            return n;
1031b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        } else if (n == 0) {
1041b86fe063badb5f28c467ade39be0f4008688947Andreas Huber            break;
1051b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        }
1061b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1071b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        numBytesRead += n;
1081b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1091b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1101b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
1111b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1121b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    addBandwidthMeasurement(numBytesRead, delayUs);
1131b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1141b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return numBytesRead;
1151b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1161b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1171b86fe063badb5f28c467ade39be0f4008688947Andreas Huberstatus_t MediaHTTP::getSize(off64_t *size) {
1181b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mInitCheck != OK) {
1191b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return mInitCheck;
1201b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1211b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1221b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    // Caching the returned size so that it stays valid even after a
1231b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    // disconnect. NuCachedSource2 relies on this.
1241b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1251b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (!mCachedSizeValid) {
1261b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mCachedSize = mHTTPConnection->getSize();
1271b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mCachedSizeValid = true;
1281b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1291b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1301b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    *size = mCachedSize;
1311b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1321b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return *size < 0 ? *size : OK;
1331b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1341b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1351b86fe063badb5f28c467ade39be0f4008688947Andreas Huberuint32_t MediaHTTP::flags() {
1361b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return kWantsPrefetching | kIsHTTPBasedSource;
1371b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1381b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1391b86fe063badb5f28c467ade39be0f4008688947Andreas Huberstatus_t MediaHTTP::reconnectAtOffset(off64_t offset) {
1401b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return connect(mLastURI.c_str(), &mLastHeaders, offset);
1411b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1421b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1431b86fe063badb5f28c467ade39be0f4008688947Andreas Huber// DRM...
1441b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1451b86fe063badb5f28c467ade39be0f4008688947Andreas Hubersp<DecryptHandle> MediaHTTP::DrmInitialization(const char* mime) {
1461b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mDrmManagerClient == NULL) {
1471b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mDrmManagerClient = new DrmManagerClient();
1481b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1491b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1501b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mDrmManagerClient == NULL) {
1511b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return NULL;
1521b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1531b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1541b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mDecryptHandle == NULL) {
1551b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mDecryptHandle = mDrmManagerClient->openDecryptSession(
1561b86fe063badb5f28c467ade39be0f4008688947Andreas Huber                String8(mLastURI.c_str()), mime);
1571b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1581b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1591b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mDecryptHandle == NULL) {
1601b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        delete mDrmManagerClient;
1611b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mDrmManagerClient = NULL;
1621b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1631b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1641b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return mDecryptHandle;
1651b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1661b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1671b86fe063badb5f28c467ade39be0f4008688947Andreas Hubervoid MediaHTTP::getDrmInfo(
1681b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        sp<DecryptHandle> &handle, DrmManagerClient **client) {
1691b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    handle = mDecryptHandle;
1701b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    *client = mDrmManagerClient;
1711b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1721b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1731b86fe063badb5f28c467ade39be0f4008688947Andreas HuberString8 MediaHTTP::getUri() {
174c9c7e25a4b1c34439fb365f6cfbef063884566ccMarco Nelissen    String8 uri;
175c9c7e25a4b1c34439fb365f6cfbef063884566ccMarco Nelissen    if (OK == mHTTPConnection->getUri(&uri)) {
176c9c7e25a4b1c34439fb365f6cfbef063884566ccMarco Nelissen        return uri;
177c9c7e25a4b1c34439fb365f6cfbef063884566ccMarco Nelissen    }
1781b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return String8(mLastURI.c_str());
1791b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1801b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1811b86fe063badb5f28c467ade39be0f4008688947Andreas HuberString8 MediaHTTP::getMIMEType() const {
1821b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mInitCheck != OK) {
1831b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return String8("application/octet-stream");
1841b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1851b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1861b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    String8 mimeType;
1871b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    status_t err = mHTTPConnection->getMIMEType(&mimeType);
1881b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1891b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (err != OK) {
1901b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        return String8("application/octet-stream");
1911b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
1921b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1931b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    return mimeType;
1941b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
1951b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
1961b86fe063badb5f28c467ade39be0f4008688947Andreas Hubervoid MediaHTTP::clearDRMState_l() {
1971b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    if (mDecryptHandle != NULL) {
1981b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        // To release mDecryptHandle
1991b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        CHECK(mDrmManagerClient);
2001b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
2011b86fe063badb5f28c467ade39be0f4008688947Andreas Huber        mDecryptHandle = NULL;
2021b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    }
2031b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}
2041b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
2051b86fe063badb5f28c467ade39be0f4008688947Andreas Huber}  // namespace android
206