Home | History | Annotate | Download | only in http
      1 /*
      2  * Copyright (C) 2013 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 "MediaHTTP"
     19 #include <utils/Log.h>
     20 
     21 #include <media/stagefright/MediaHTTP.h>
     22 
     23 #include <binder/IServiceManager.h>
     24 #include <media/stagefright/foundation/ADebug.h>
     25 #include <media/stagefright/foundation/ALooper.h>
     26 #include <media/stagefright/Utils.h>
     27 
     28 #include <media/IMediaHTTPConnection.h>
     29 
     30 namespace android {
     31 
     32 MediaHTTP::MediaHTTP(const sp<IMediaHTTPConnection> &conn)
     33     : mInitCheck((conn != NULL) ? OK : NO_INIT),
     34       mHTTPConnection(conn),
     35       mCachedSizeValid(false),
     36       mCachedSize(0ll),
     37       mDrmManagerClient(NULL) {
     38 }
     39 
     40 MediaHTTP::~MediaHTTP() {
     41     clearDRMState_l();
     42 }
     43 
     44 status_t MediaHTTP::connect(
     45         const char *uri,
     46         const KeyedVector<String8, String8> *headers,
     47         off64_t /* offset */) {
     48     if (mInitCheck != OK) {
     49         return mInitCheck;
     50     }
     51 
     52     KeyedVector<String8, String8> extHeaders;
     53     if (headers != NULL) {
     54         extHeaders = *headers;
     55     }
     56 
     57     if (extHeaders.indexOfKey(String8("User-Agent")) < 0) {
     58         extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str()));
     59     }
     60 
     61     bool success = mHTTPConnection->connect(uri, &extHeaders);
     62 
     63     mLastHeaders = extHeaders;
     64     mLastURI = uri;
     65 
     66     mCachedSizeValid = false;
     67 
     68     return success ? OK : UNKNOWN_ERROR;
     69 }
     70 
     71 void MediaHTTP::disconnect() {
     72     if (mInitCheck != OK) {
     73         return;
     74     }
     75 
     76     mHTTPConnection->disconnect();
     77 }
     78 
     79 status_t MediaHTTP::initCheck() const {
     80     return mInitCheck;
     81 }
     82 
     83 ssize_t MediaHTTP::readAt(off64_t offset, void *data, size_t size) {
     84     if (mInitCheck != OK) {
     85         return mInitCheck;
     86     }
     87 
     88     int64_t startTimeUs = ALooper::GetNowUs();
     89 
     90     size_t numBytesRead = 0;
     91     while (numBytesRead < size) {
     92         size_t copy = size - numBytesRead;
     93 
     94         if (copy > 64 * 1024) {
     95             // limit the buffer sizes transferred across binder boundaries
     96             // to avoid spurious transaction failures.
     97             copy = 64 * 1024;
     98         }
     99 
    100         ssize_t n = mHTTPConnection->readAt(
    101                 offset + numBytesRead, (uint8_t *)data + numBytesRead, copy);
    102 
    103         if (n < 0) {
    104             return n;
    105         } else if (n == 0) {
    106             break;
    107         }
    108 
    109         numBytesRead += n;
    110     }
    111 
    112     int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
    113 
    114     addBandwidthMeasurement(numBytesRead, delayUs);
    115 
    116     return numBytesRead;
    117 }
    118 
    119 status_t MediaHTTP::getSize(off64_t *size) {
    120     if (mInitCheck != OK) {
    121         return mInitCheck;
    122     }
    123 
    124     // Caching the returned size so that it stays valid even after a
    125     // disconnect. NuCachedSource2 relies on this.
    126 
    127     if (!mCachedSizeValid) {
    128         mCachedSize = mHTTPConnection->getSize();
    129         mCachedSizeValid = true;
    130     }
    131 
    132     *size = mCachedSize;
    133 
    134     return *size < 0 ? *size : static_cast<status_t>(OK);
    135 }
    136 
    137 uint32_t MediaHTTP::flags() {
    138     return kWantsPrefetching | kIsHTTPBasedSource;
    139 }
    140 
    141 status_t MediaHTTP::reconnectAtOffset(off64_t offset) {
    142     return connect(mLastURI.c_str(), &mLastHeaders, offset);
    143 }
    144 
    145 // DRM...
    146 
    147 sp<DecryptHandle> MediaHTTP::DrmInitialization(const char* mime) {
    148     if (mDrmManagerClient == NULL) {
    149         mDrmManagerClient = new DrmManagerClient();
    150     }
    151 
    152     if (mDrmManagerClient == NULL) {
    153         return NULL;
    154     }
    155 
    156     if (mDecryptHandle == NULL) {
    157         mDecryptHandle = mDrmManagerClient->openDecryptSession(
    158                 String8(mLastURI.c_str()), mime);
    159     }
    160 
    161     if (mDecryptHandle == NULL) {
    162         delete mDrmManagerClient;
    163         mDrmManagerClient = NULL;
    164     }
    165 
    166     return mDecryptHandle;
    167 }
    168 
    169 void MediaHTTP::getDrmInfo(
    170         sp<DecryptHandle> &handle, DrmManagerClient **client) {
    171     handle = mDecryptHandle;
    172     *client = mDrmManagerClient;
    173 }
    174 
    175 String8 MediaHTTP::getUri() {
    176     if (mInitCheck != OK) {
    177         return String8::empty();
    178     }
    179 
    180     String8 uri;
    181     if (OK == mHTTPConnection->getUri(&uri)) {
    182         return uri;
    183     }
    184     return String8(mLastURI.c_str());
    185 }
    186 
    187 String8 MediaHTTP::getMIMEType() const {
    188     if (mInitCheck != OK) {
    189         return String8("application/octet-stream");
    190     }
    191 
    192     String8 mimeType;
    193     status_t err = mHTTPConnection->getMIMEType(&mimeType);
    194 
    195     if (err != OK) {
    196         return String8("application/octet-stream");
    197     }
    198 
    199     return mimeType;
    200 }
    201 
    202 void MediaHTTP::clearDRMState_l() {
    203     if (mDecryptHandle != NULL) {
    204         // To release mDecryptHandle
    205         CHECK(mDrmManagerClient);
    206         mDrmManagerClient->closeDecryptSession(mDecryptHandle);
    207         mDecryptHandle = NULL;
    208     }
    209 }
    210 
    211 }  // namespace android
    212