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