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