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