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(NO_INIT), 34 mHTTPConnection(conn), 35 mCachedSizeValid(false), 36 mCachedSize(0ll), 37 mDrmManagerClient(NULL) { 38 mInitCheck = OK; 39} 40 41MediaHTTP::~MediaHTTP() { 42 clearDRMState_l(); 43} 44 45status_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 69void MediaHTTP::disconnect() { 70 if (mInitCheck != OK) { 71 return; 72 } 73 74 mHTTPConnection->disconnect(); 75} 76 77status_t MediaHTTP::initCheck() const { 78 return mInitCheck; 79} 80 81ssize_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 117status_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 135uint32_t MediaHTTP::flags() { 136 return kWantsPrefetching | kIsHTTPBasedSource; 137} 138 139status_t MediaHTTP::reconnectAtOffset(off64_t offset) { 140 return connect(mLastURI.c_str(), &mLastHeaders, offset); 141} 142 143// DRM... 144 145sp<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 167void MediaHTTP::getDrmInfo( 168 sp<DecryptHandle> &handle, DrmManagerClient **client) { 169 handle = mDecryptHandle; 170 *client = mDrmManagerClient; 171} 172 173String8 MediaHTTP::getUri() { 174 String8 uri; 175 if (OK == mHTTPConnection->getUri(&uri)) { 176 return uri; 177 } 178 return String8(mLastURI.c_str()); 179} 180 181String8 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 196void 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