1a44153c1a57202fb538659eb50706e60454d6273Andreas Huber/*
2a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Copyright (C) 2010 The Android Open Source Project
3a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *
4a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * you may not use this file except in compliance with the License.
6a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * You may obtain a copy of the License at
7a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *
8a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9a44153c1a57202fb538659eb50706e60454d6273Andreas Huber *
10a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * Unless required by applicable law or agreed to in writing, software
11a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * See the License for the specific language governing permissions and
14a44153c1a57202fb538659eb50706e60454d6273Andreas Huber * limitations under the License.
15a44153c1a57202fb538659eb50706e60454d6273Andreas Huber */
16a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
17a44153c1a57202fb538659eb50706e60454d6273Andreas Huber//#define LOG_NDEBUG 0
18a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#define LOG_TAG "LiveSession"
19a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <utils/Log.h>
20a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
21a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include "include/LiveSession.h"
22a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
23a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include "LiveDataSource.h"
24a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
25a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include "include/M3UParser.h"
261156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include "include/HTTPBase.h"
27a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
28a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <cutils/properties.h>
29a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/hexdump.h>
30a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
31a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/ADebug.h>
32a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/foundation/AMessage.h>
33a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/DataSource.h>
34a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/FileSource.h>
35a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <media/stagefright/MediaErrors.h>
36a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
37a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <ctype.h>
38a44153c1a57202fb538659eb50706e60454d6273Andreas Huber#include <openssl/aes.h>
397e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#include <openssl/md5.h>
40a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
41a44153c1a57202fb538659eb50706e60454d6273Andreas Hubernamespace android {
42a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
439b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas HuberLiveSession::LiveSession(uint32_t flags, bool uidValid, uid_t uid)
447314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber    : mFlags(flags),
459b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber      mUIDValid(uidValid),
469b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber      mUID(uid),
477314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber      mDataSource(new LiveDataSource),
487314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber      mHTTPDataSource(
491156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber              HTTPBase::Create(
507314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber                  (mFlags & kFlagIncognito)
511156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    ? HTTPBase::kFlagIncognito
527314fa17093d514199fedcb55ac41136a1b31cb3Andreas Huber                    : 0)),
53a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mPrevBandwidthIndex(-1),
54a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mLastPlaylistFetchTimeUs(-1),
55a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mSeqNumber(-1),
56a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mSeekTimeUs(-1),
57a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mNumRetries(0),
58a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mDurationUs(-1),
59a44153c1a57202fb538659eb50706e60454d6273Andreas Huber      mSeekDone(false),
60ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber      mDisconnectPending(false),
617e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber      mMonitorQueueGeneration(0),
627e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber      mRefreshState(INITIAL_MINIMUM_RELOAD_DELAY) {
639b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber    if (mUIDValid) {
649b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber        mHTTPDataSource->setUID(mUID);
659b80c2bdb205bc143104f54d0743b6eedd67b14eAndreas Huber    }
66a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
67a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
68a44153c1a57202fb538659eb50706e60454d6273Andreas HuberLiveSession::~LiveSession() {
69a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
70a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
71a44153c1a57202fb538659eb50706e60454d6273Andreas Hubersp<DataSource> LiveSession::getDataSource() {
72a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return mDataSource;
73a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
74a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
75ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Hubervoid LiveSession::connect(
76ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        const char *url, const KeyedVector<String8, String8> *headers) {
77a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatConnect, id());
78a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setString("url", url);
79ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
80ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (headers != NULL) {
81ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        msg->setPointer(
82ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                "headers",
83ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber                new KeyedVector<String8, String8>(*headers));
84ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
85ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
86a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
87a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
88a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
89a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::disconnect() {
90ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    Mutex::Autolock autoLock(mLock);
91ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    mDisconnectPending = true;
92ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
93ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    mHTTPDataSource->disconnect();
94ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
95a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    (new AMessage(kWhatDisconnect, id()))->post();
96a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
97a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
98a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::seekTo(int64_t timeUs) {
99a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    Mutex::Autolock autoLock(mLock);
100a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mSeekDone = false;
101a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
102a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSeek, id());
103a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->setInt64("timeUs", timeUs);
104a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    msg->post();
105a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
106a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    while (!mSeekDone) {
107a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mCondition.wait(mLock);
108a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
109a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
110a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
111a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onMessageReceived(const sp<AMessage> &msg) {
112a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    switch (msg->what()) {
113a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatConnect:
114a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onConnect(msg);
115a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
116a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
117a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatDisconnect:
118a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onDisconnect();
119a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
120a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
121a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatMonitorQueue:
122a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        {
123a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            int32_t generation;
124a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(msg->findInt32("generation", &generation));
125a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
126a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            if (generation != mMonitorQueueGeneration) {
127a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                // Stale event
128a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                break;
129a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            }
130a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
131a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onMonitorQueue();
132a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
133a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
134a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
135a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        case kWhatSeek:
136a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            onSeek(msg);
137a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
138a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
139a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        default:
140a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            TRESPASS();
141a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
142a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
143a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
144a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
145a44153c1a57202fb538659eb50706e60454d6273Andreas Huber// static
146a44153c1a57202fb538659eb50706e60454d6273Andreas Huberint LiveSession::SortByBandwidth(const BandwidthItem *a, const BandwidthItem *b) {
147a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (a->mBandwidth < b->mBandwidth) {
148a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return -1;
149a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else if (a->mBandwidth == b->mBandwidth) {
150a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return 0;
151a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
152a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
153a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return 1;
154a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
155a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
156a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onConnect(const sp<AMessage> &msg) {
157a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    AString url;
158a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    CHECK(msg->findString("url", &url));
159a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
160ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    KeyedVector<String8, String8> *headers = NULL;
161ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    if (!msg->findPointer("headers", (void **)&headers)) {
162ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders.clear();
163ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    } else {
164ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        mExtraHeaders = *headers;
165ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
166ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        delete headers;
167ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber        headers = NULL;
168ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber    }
169ad0d9c9c39a24b7fbd94e935a5855c9025341929Andreas Huber
17053ae1640ffbfc690962f7f94694b02680c6f66cbJames Dong    ALOGI("onConnect <URL suppressed>");
171a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
172a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mMasterURL = url;
173a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
1747e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    bool dummy;
1757e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    sp<M3UParser> playlist = fetchPlaylist(url.c_str(), &dummy);
176ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
177ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    if (playlist == NULL) {
17829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("unable to fetch master playlist '%s'.", url.c_str());
179ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
180ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        mDataSource->queueEOS(ERROR_IO);
181ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        return;
182ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    }
183a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
184a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (playlist->isVariantPlaylist()) {
185a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        for (size_t i = 0; i < playlist->size(); ++i) {
186a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            BandwidthItem item;
187a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
188a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<AMessage> meta;
189a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            playlist->itemAt(i, &item.mURI, &meta);
190a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
191a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            unsigned long bandwidth;
192a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            CHECK(meta->findInt32("bandwidth", (int32_t *)&item.mBandwidth));
193a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
194a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            mBandwidthItems.push(item);
195a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
196a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
197a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        CHECK_GT(mBandwidthItems.size(), 0u);
198a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
199a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        mBandwidthItems.sort(SortByBandwidth);
200a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
201a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
202a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    postMonitorQueue();
203a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
204a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
205a44153c1a57202fb538659eb50706e60454d6273Andreas Hubervoid LiveSession::onDisconnect() {
206df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("onDisconnect");
207a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
208a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    mDataSource->queueEOS(ERROR_END_OF_STREAM);
209ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
210ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    Mutex::Autolock autoLock(mLock);
211ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber    mDisconnectPending = false;
212a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
213a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2142aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huberstatus_t LiveSession::fetchFile(
2152aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        const char *url, sp<ABuffer> *out,
2162aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        int64_t range_offset, int64_t range_length) {
217a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = NULL;
218a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
219a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<DataSource> source;
220a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
221a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (!strncasecmp(url, "file://", 7)) {
222a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        source = new FileSource(url + 7);
2238cb0c4168bf4b678e4a6edfcf409247016be20d5Andreas Huber    } else if (strncasecmp(url, "http://", 7)
2248cb0c4168bf4b678e4a6edfcf409247016be20d5Andreas Huber            && strncasecmp(url, "https://", 8)) {
225df42f949c8bd05b81d94633767514fff88f52062Andreas Huber        return ERROR_UNSUPPORTED;
226a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
227ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        {
228ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            Mutex::Autolock autoLock(mLock);
229ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
230ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            if (mDisconnectPending) {
231ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber                return ERROR_IO;
232ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber            }
233ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber        }
234ab8a0badb8fb1e294dacf2eb6a891439f348aff9Andreas Huber
2352aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        KeyedVector<String8, String8> headers = mExtraHeaders;
2362aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        if (range_offset > 0 || range_length >= 0) {
2372aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            headers.add(
2382aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    String8("Range"),
2392aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    String8(
2402aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                        StringPrintf(
2412aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                            "bytes=%lld-%s",
2422aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                            range_offset,
2432aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                            range_length < 0
2442aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                                ? "" : StringPrintf("%lld", range_offset + range_length - 1).c_str()).c_str()));
2452aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        }
2462aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        status_t err = mHTTPDataSource->connect(url, &headers);
247a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
248a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (err != OK) {
249a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            return err;
250a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
251a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
252a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        source = mHTTPDataSource;
253a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
254a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
255a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    off64_t size;
256a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    status_t err = source->getSize(&size);
257a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
258a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (err != OK) {
259a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size = 65536;
260a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
261a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
262a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer = new ABuffer(size);
263a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    buffer->setRange(0, 0);
264a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
265a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    for (;;) {
266a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        size_t bufferRemaining = buffer->capacity() - buffer->size();
267a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
268a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (bufferRemaining == 0) {
269a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            bufferRemaining = 32768;
270a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("increasing download buffer to %d bytes",
272a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                 buffer->size() + bufferRemaining);
273a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
274a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
275a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            memcpy(copy->data(), buffer->data(), buffer->size());
276a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            copy->setRange(0, buffer->size());
277a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
278a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            buffer = copy;
279a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
280a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
2812aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        size_t maxBytesToRead = bufferRemaining;
2822aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        if (range_length >= 0) {
2832aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            int64_t bytesLeftInRange = range_length - buffer->size();
2842aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            if (bytesLeftInRange < maxBytesToRead) {
2852aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead = bytesLeftInRange;
2862aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
2872aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                if (bytesLeftInRange == 0) {
2882aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                    break;
2892aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                }
2902aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber            }
2912aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber        }
2922aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber
293a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        ssize_t n = source->readAt(
294a44153c1a57202fb538659eb50706e60454d6273Andreas Huber                buffer->size(), buffer->data() + buffer->size(),
2952aa4cc04154d82f6658fb86f394f13bb488b0468Andreas Huber                maxBytesToRead);
296a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
297a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n < 0) {
29820ad3a341a96e7746015ccb7369fa567897e11f6Andreas Huber            return n;
299a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
300a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
301a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        if (n == 0) {
302a44153c1a57202fb538659eb50706e60454d6273Andreas Huber            break;
303a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        }
304a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
305a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        buffer->setRange(0, buffer->size() + (size_t)n);
306a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
307a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
308a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    *out = buffer;
309a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
310a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    return OK;
311a44153c1a57202fb538659eb50706e60454d6273Andreas Huber}
312a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
3137e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Hubersp<M3UParser> LiveSession::fetchPlaylist(const char *url, bool *unchanged) {
3147e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    *unchanged = false;
3157e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
316a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    sp<ABuffer> buffer;
317a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    status_t err = fetchFile(url, &buffer);
318a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
319a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    if (err != OK) {
320a44153c1a57202fb538659eb50706e60454d6273Andreas Huber        return NULL;
321a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    }
322a44153c1a57202fb538659eb50706e60454d6273Andreas Huber
3237e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // MD5 functionality is not available on the simulator, treat all
3247e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    // playlists as changed.
3257e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3267e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber#if defined(HAVE_ANDROID_OS)
3277e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    uint8_t hash[16];
3287e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3297e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_CTX m;
3307e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Init(&m);
3317e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Update(&m, buffer->data(), buffer->size());
3327e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3337e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    MD5_Final(hash, &m);
3347e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3357e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    if (mPlaylist != NULL && !memcmp(hash, mPlaylistHash, 16)) {
3367e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        // playlist unchanged
3377e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3387e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        if (mRefreshState != THIRD_UNCHANGED_RELOAD_ATTEMPT) {
3397e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber            mRefreshState = (RefreshState)(mRefreshState + 1);
3407e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        }
3417e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3427e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        *unchanged = true;
3437e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Playlist unchanged, refresh state is now %d",
3457e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber             (int)mRefreshState);
3467e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3477e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber        return NULL;
3487e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    }
3497e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
3507e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber    memcpy(mPlaylistHash, hash, sizeof(hash));
3517e43a5a2dcfa9bc64ef477472a33c87a84695c09Andreas Huber
352