blob: 180460b5e33dd71103e05cbad5144be1473508b4 [file] [log] [blame]
Andreas Huber5f5719e2011-03-08 15:59:28 -08001/*
2 * Copyright (C) 2011 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 "ChromiumHTTPDataSource"
19#include <media/stagefright/foundation/ADebug.h>
20
21#include "include/ChromiumHTTPDataSource.h"
22
23#include <media/stagefright/foundation/ALooper.h>
24#include <media/stagefright/MediaErrors.h>
25
26#include "support.h"
27
Andreas Huber178e8eb2011-07-18 13:47:55 -070028#include <cutils/properties.h> // for property_get
29
Andreas Huber5f5719e2011-03-08 15:59:28 -080030namespace android {
31
32ChromiumHTTPDataSource::ChromiumHTTPDataSource(uint32_t flags)
33 : mFlags(flags),
34 mState(DISCONNECTED),
35 mDelegate(new SfDelegate),
36 mCurrentOffset(0),
37 mIOResult(OK),
38 mContentSize(-1),
Andreas Huber5f5719e2011-03-08 15:59:28 -080039 mDecryptHandle(NULL),
40 mDrmManagerClient(NULL) {
41 mDelegate->setOwner(this);
42}
43
44ChromiumHTTPDataSource::~ChromiumHTTPDataSource() {
45 disconnect();
46
47 delete mDelegate;
48 mDelegate = NULL;
49
Gloria Wang1467ec32011-08-04 16:01:35 -070050 clearDRMState_l();
51
Andreas Huber5f5719e2011-03-08 15:59:28 -080052 if (mDrmManagerClient != NULL) {
53 delete mDrmManagerClient;
54 mDrmManagerClient = NULL;
55 }
56}
57
58status_t ChromiumHTTPDataSource::connect(
59 const char *uri,
60 const KeyedVector<String8, String8> *headers,
61 off64_t offset) {
62 Mutex::Autolock autoLock(mLock);
63
Ashish Sharmad5a20d82011-07-07 17:57:05 -070064 uid_t uid;
65 if (getUID(&uid)) {
66 mDelegate->setUID(uid);
67 }
68 LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG, "connect on behalf of uid %d", uid);
69
Andreas Huber5f5719e2011-03-08 15:59:28 -080070 return connect_l(uri, headers, offset);
71}
72
73status_t ChromiumHTTPDataSource::connect_l(
74 const char *uri,
75 const KeyedVector<String8, String8> *headers,
76 off64_t offset) {
77 if (mState != DISCONNECTED) {
78 disconnect_l();
79 }
80
81 if (!(mFlags & kFlagIncognito)) {
82 LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "connect to %s @%lld", uri, offset);
83 } else {
84 LOG_PRI(ANDROID_LOG_INFO, LOG_TAG,
85 "connect to <URL suppressed> @%lld", offset);
86 }
87
88 mURI = uri;
Andreas Hubera2e57ca2011-03-30 11:15:27 -070089 mContentType = String8("application/octet-stream");
Andreas Huber5f5719e2011-03-08 15:59:28 -080090
91 if (headers != NULL) {
92 mHeaders = *headers;
93 } else {
94 mHeaders.clear();
95 }
96
97 mState = CONNECTING;
98 mContentSize = -1;
99 mCurrentOffset = offset;
100
101 mDelegate->initiateConnection(mURI.c_str(), &mHeaders, offset);
102
103 while (mState == CONNECTING) {
104 mCondition.wait(mLock);
105 }
106
107 return mState == CONNECTED ? OK : mIOResult;
108}
109
Andreas Hubera2e57ca2011-03-30 11:15:27 -0700110void ChromiumHTTPDataSource::onConnectionEstablished(
111 int64_t contentSize, const char *contentType) {
Andreas Huber5f5719e2011-03-08 15:59:28 -0800112 Mutex::Autolock autoLock(mLock);
113 mState = CONNECTED;
114 mContentSize = (contentSize < 0) ? -1 : contentSize + mCurrentOffset;
Andreas Hubera2e57ca2011-03-30 11:15:27 -0700115 mContentType = String8(contentType);
Andreas Huber5f5719e2011-03-08 15:59:28 -0800116 mCondition.broadcast();
117}
118
119void ChromiumHTTPDataSource::onConnectionFailed(status_t err) {
120 Mutex::Autolock autoLock(mLock);
121 mState = DISCONNECTED;
122 mCondition.broadcast();
123
Andreas Huber178e8eb2011-07-18 13:47:55 -0700124 // mURI.clear();
Andreas Huber5f5719e2011-03-08 15:59:28 -0800125
126 mIOResult = err;
Andreas Huber5f5719e2011-03-08 15:59:28 -0800127}
128
129void ChromiumHTTPDataSource::disconnect() {
130 Mutex::Autolock autoLock(mLock);
131 disconnect_l();
132}
133
134void ChromiumHTTPDataSource::disconnect_l() {
135 if (mState == DISCONNECTED) {
136 return;
137 }
138
139 mState = DISCONNECTING;
140 mIOResult = -EINTR;
141
142 mDelegate->initiateDisconnect();
143
144 while (mState == DISCONNECTING) {
145 mCondition.wait(mLock);
146 }
147
148 CHECK_EQ((int)mState, (int)DISCONNECTED);
149}
150
151status_t ChromiumHTTPDataSource::initCheck() const {
152 Mutex::Autolock autoLock(mLock);
153
154 return mState == CONNECTED ? OK : NO_INIT;
155}
156
157ssize_t ChromiumHTTPDataSource::readAt(off64_t offset, void *data, size_t size) {
158 Mutex::Autolock autoLock(mLock);
159
160 if (mState != CONNECTED) {
Andreas Huber178e8eb2011-07-18 13:47:55 -0700161 return INVALID_OPERATION;
Andreas Huber5f5719e2011-03-08 15:59:28 -0800162 }
163
Andreas Huber178e8eb2011-07-18 13:47:55 -0700164#if 0
165 char value[PROPERTY_VALUE_MAX];
166 if (property_get("media.stagefright.disable-net", value, 0)
167 && (!strcasecmp(value, "true") || !strcmp(value, "1"))) {
168 LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Simulating that the network is down.");
169 disconnect_l();
170 return ERROR_IO;
171 }
172#endif
173
Andreas Huber5f5719e2011-03-08 15:59:28 -0800174 if (offset != mCurrentOffset) {
175 AString tmp = mURI;
176 KeyedVector<String8, String8> tmpHeaders = mHeaders;
177
178 disconnect_l();
179
180 status_t err = connect_l(tmp.c_str(), &tmpHeaders, offset);
181
182 if (err != OK) {
183 return err;
184 }
185 }
186
187 mState = READING;
188
189 int64_t startTimeUs = ALooper::GetNowUs();
190
191 mDelegate->initiateRead(data, size);
192
193 while (mState == READING) {
194 mCondition.wait(mLock);
195 }
196
197 if (mIOResult < OK) {
198 return mIOResult;
199 }
200
201 if (mState == CONNECTED) {
202 int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
203
204 // The read operation was successful, mIOResult contains
205 // the number of bytes read.
James Donga9d0feb2011-05-25 19:37:03 -0700206 addBandwidthMeasurement(mIOResult, delayUs);
Andreas Huber5f5719e2011-03-08 15:59:28 -0800207
208 mCurrentOffset += mIOResult;
209 return mIOResult;
210 }
211
212 return ERROR_IO;
213}
214
215void ChromiumHTTPDataSource::onReadCompleted(ssize_t size) {
216 Mutex::Autolock autoLock(mLock);
217
218 mIOResult = size;
219
220 if (mState == READING) {
221 mState = CONNECTED;
222 mCondition.broadcast();
223 }
224}
225
226status_t ChromiumHTTPDataSource::getSize(off64_t *size) {
227 Mutex::Autolock autoLock(mLock);
228
229 if (mContentSize < 0) {
230 return ERROR_UNSUPPORTED;
231 }
232
233 *size = mContentSize;
234
235 return OK;
236}
237
238uint32_t ChromiumHTTPDataSource::flags() {
James Dong44328702011-06-01 15:27:20 -0700239 return kWantsPrefetching | kIsHTTPBasedSource;
Andreas Huber5f5719e2011-03-08 15:59:28 -0800240}
241
242// static
243void ChromiumHTTPDataSource::InitiateRead(
244 ChromiumHTTPDataSource *me, void *data, size_t size) {
245 me->initiateRead(data, size);
246}
247
248void ChromiumHTTPDataSource::initiateRead(void *data, size_t size) {
249 mDelegate->initiateRead(data, size);
250}
251
252void ChromiumHTTPDataSource::onDisconnectComplete() {
253 Mutex::Autolock autoLock(mLock);
254 CHECK_EQ((int)mState, (int)DISCONNECTING);
255
256 mState = DISCONNECTED;
Andreas Huber178e8eb2011-07-18 13:47:55 -0700257 // mURI.clear();
Andreas Huber5f5719e2011-03-08 15:59:28 -0800258
259 mCondition.broadcast();
Andreas Huber5f5719e2011-03-08 15:59:28 -0800260}
261
Gloria Wangae775272011-02-24 16:40:57 -0800262sp<DecryptHandle> ChromiumHTTPDataSource::DrmInitialization() {
Andreas Huber5f5719e2011-03-08 15:59:28 -0800263 Mutex::Autolock autoLock(mLock);
264
265 if (mDrmManagerClient == NULL) {
266 mDrmManagerClient = new DrmManagerClient();
267 }
268
269 if (mDrmManagerClient == NULL) {
270 return NULL;
271 }
272
273 if (mDecryptHandle == NULL) {
274 /* Note if redirect occurs, mUri is the redirect uri instead of the
275 * original one
276 */
277 mDecryptHandle = mDrmManagerClient->openDecryptSession(
278 String8(mURI.c_str()));
279 }
280
281 if (mDecryptHandle == NULL) {
282 delete mDrmManagerClient;
283 mDrmManagerClient = NULL;
284 }
285
286 return mDecryptHandle;
287}
288
289void ChromiumHTTPDataSource::getDrmInfo(
Gloria Wangae775272011-02-24 16:40:57 -0800290 sp<DecryptHandle> &handle, DrmManagerClient **client) {
Andreas Huber5f5719e2011-03-08 15:59:28 -0800291 Mutex::Autolock autoLock(mLock);
292
Gloria Wangae775272011-02-24 16:40:57 -0800293 handle = mDecryptHandle;
Andreas Huber5f5719e2011-03-08 15:59:28 -0800294 *client = mDrmManagerClient;
295}
296
297String8 ChromiumHTTPDataSource::getUri() {
298 Mutex::Autolock autoLock(mLock);
299
300 return String8(mURI.c_str());
301}
302
Andreas Hubera2e57ca2011-03-30 11:15:27 -0700303String8 ChromiumHTTPDataSource::getMIMEType() const {
304 Mutex::Autolock autoLock(mLock);
305
306 return mContentType;
307}
308
Andreas Huber5f5719e2011-03-08 15:59:28 -0800309void ChromiumHTTPDataSource::clearDRMState_l() {
310 if (mDecryptHandle != NULL) {
311 // To release mDecryptHandle
312 CHECK(mDrmManagerClient);
313 mDrmManagerClient->closeDecryptSession(mDecryptHandle);
314 mDecryptHandle = NULL;
315 }
316}
317
Andreas Huber178e8eb2011-07-18 13:47:55 -0700318status_t ChromiumHTTPDataSource::reconnectAtOffset(off64_t offset) {
319 Mutex::Autolock autoLock(mLock);
320
321 if (mURI.empty()) {
322 return INVALID_OPERATION;
323 }
324
325 LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Reconnecting...");
326 status_t err = connect_l(mURI.c_str(), &mHeaders, offset);
327 if (err != OK) {
328 LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Reconnect failed w/ err 0x%08x", err);
329 }
330
331 return err;
332}
333
Andreas Huber5f5719e2011-03-08 15:59:28 -0800334} // namespace android
335