1fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber/*
2fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * Copyright 2012, The Android Open Source Project
3fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber *
4fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * you may not use this file except in compliance with the License.
6fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * You may obtain a copy of the License at
7fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber *
8fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber *     http://www.apache.org/licenses/LICENSE-2.0
9fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber *
10fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * Unless required by applicable law or agreed to in writing, software
11fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * See the License for the specific language governing permissions and
14fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber * limitations under the License.
15fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber */
16fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
17fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber//#define LOG_NDEBUG 0
18fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#define LOG_TAG "TunnelRenderer"
19fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <utils/Log.h>
20fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
21fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include "TunnelRenderer.h"
22fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
23fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include "ATSParser.h"
24fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
25fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <binder/IMemory.h>
26fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <binder/IServiceManager.h>
27fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <gui/SurfaceComposerClient.h>
28fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/IMediaPlayerService.h>
29fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/IStreamSource.h>
30fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
31fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/stagefright/foundation/ADebug.h>
32fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <media/stagefright/foundation/AMessage.h>
33fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber#include <ui/DisplayInfo.h>
34fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
35fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubernamespace android {
36fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
37fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstruct TunnelRenderer::PlayerClient : public BnMediaPlayerClient {
38fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    PlayerClient() {}
39fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
40fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    virtual void notify(int msg, int ext1, int ext2, const Parcel *obj) {
41fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        ALOGI("notify %d, %d, %d", msg, ext1, ext2);
42fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
43fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
44fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberprotected:
45fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    virtual ~PlayerClient() {}
46fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
47fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberprivate:
48fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(PlayerClient);
49fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber};
50fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
51fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberstruct TunnelRenderer::StreamSource : public BnStreamSource {
52fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    StreamSource(TunnelRenderer *owner);
53fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
54fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    virtual void setListener(const sp<IStreamListener> &listener);
55fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    virtual void setBuffers(const Vector<sp<IMemory> > &buffers);
56fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
57fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    virtual void onBufferAvailable(size_t index);
58fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
59fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    virtual uint32_t flags() const;
60fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
61fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    void doSomeWork();
62fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
63fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberprotected:
64fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    virtual ~StreamSource();
65fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
66fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberprivate:
67fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mutable Mutex mLock;
68fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
69fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    TunnelRenderer *mOwner;
70fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
71fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<IStreamListener> mListener;
72fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
73fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    Vector<sp<IMemory> > mBuffers;
74fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    List<size_t> mIndicesAvailable;
75fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
76fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    size_t mNumDeqeued;
77fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
78fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(StreamSource);
79fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber};
80fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
81fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber////////////////////////////////////////////////////////////////////////////////
82fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
83fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas HuberTunnelRenderer::StreamSource::StreamSource(TunnelRenderer *owner)
84fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    : mOwner(owner),
85fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mNumDeqeued(0) {
86fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
87fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
88fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas HuberTunnelRenderer::StreamSource::~StreamSource() {
89fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
90fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
91fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid TunnelRenderer::StreamSource::setListener(
92fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        const sp<IStreamListener> &listener) {
93fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mListener = listener;
94fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
95fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
96fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid TunnelRenderer::StreamSource::setBuffers(
97fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        const Vector<sp<IMemory> > &buffers) {
98fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mBuffers = buffers;
99fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
100fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
101fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid TunnelRenderer::StreamSource::onBufferAvailable(size_t index) {
102fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    CHECK_LT(index, mBuffers.size());
103fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
104fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    {
105fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        Mutex::Autolock autoLock(mLock);
106fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mIndicesAvailable.push_back(index);
107fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
108fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
109fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    doSomeWork();
110fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
111fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
112fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huberuint32_t TunnelRenderer::StreamSource::flags() const {
113fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    return kFlagAlignedVideoData;
114fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
115fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
116fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid TunnelRenderer::StreamSource::doSomeWork() {
117fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    Mutex::Autolock autoLock(mLock);
118fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
119fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    while (!mIndicesAvailable.empty()) {
120fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        sp<ABuffer> srcBuffer = mOwner->dequeueBuffer();
121fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (srcBuffer == NULL) {
122fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            break;
123fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
124fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
125fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        ++mNumDeqeued;
126fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
127fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (mNumDeqeued == 1) {
128fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            ALOGI("fixing real time now.");
129fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
130fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            sp<AMessage> extra = new AMessage;
131fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
132fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            extra->setInt32(
133fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    IStreamListener::kKeyDiscontinuityMask,
134fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    ATSParser::DISCONTINUITY_ABSOLUTE_TIME);
135fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
136fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            extra->setInt64("timeUs", ALooper::GetNowUs());
137fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
138fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mListener->issueCommand(
139fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    IStreamListener::DISCONTINUITY,
140fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    false /* synchronous */,
141fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    extra);
142fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
143fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
144fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        ALOGV("dequeue TS packet of size %d", srcBuffer->size());
145fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
146fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        size_t index = *mIndicesAvailable.begin();
147fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mIndicesAvailable.erase(mIndicesAvailable.begin());
148fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
149fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        sp<IMemory> mem = mBuffers.itemAt(index);
150fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        CHECK_LE(srcBuffer->size(), mem->size());
151fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        CHECK_EQ((srcBuffer->size() % 188), 0u);
152fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
153fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        memcpy(mem->pointer(), srcBuffer->data(), srcBuffer->size());
154fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mListener->queueBuffer(index, srcBuffer->size());
155fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
156fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
157fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
158fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber////////////////////////////////////////////////////////////////////////////////
159fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
160fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas HuberTunnelRenderer::TunnelRenderer(
161fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        const sp<AMessage> &notifyLost,
162fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        const sp<ISurfaceTexture> &surfaceTex)
163fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    : mNotifyLost(notifyLost),
164fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mSurfaceTex(surfaceTex),
165fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mTotalBytesQueued(0ll),
166fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mLastDequeuedExtSeqNo(-1),
167fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mFirstFailedAttemptUs(-1ll),
168fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber      mRequestedRetransmission(false) {
169fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
170fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
171fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas HuberTunnelRenderer::~TunnelRenderer() {
172fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    destroyPlayer();
173fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
174fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
175fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid TunnelRenderer::queueBuffer(const sp<ABuffer> &buffer) {
176fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    Mutex::Autolock autoLock(mLock);
177fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
178fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mTotalBytesQueued += buffer->size();
179fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
180fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (mPackets.empty()) {
181fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mPackets.push_back(buffer);
182fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return;
183fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
184fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
185fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    int32_t newExtendedSeqNo = buffer->int32Data();
186fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
187fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    List<sp<ABuffer> >::iterator firstIt = mPackets.begin();
188fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    List<sp<ABuffer> >::iterator it = --mPackets.end();
189fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    for (;;) {
190fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        int32_t extendedSeqNo = (*it)->int32Data();
191fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
192fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (extendedSeqNo == newExtendedSeqNo) {
193fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // Duplicate packet.
194fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            return;
195fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
196fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
197fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (extendedSeqNo < newExtendedSeqNo) {
198fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // Insert new packet after the one at "it".
199fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mPackets.insert(++it, buffer);
200fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            return;
201fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
202fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
203fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (it == firstIt) {
204fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            // Insert new packet before the first existing one.
205fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mPackets.insert(it, buffer);
206fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            return;
207fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
208fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
209fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        --it;
210fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
211fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
212fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
213fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubersp<ABuffer> TunnelRenderer::dequeueBuffer() {
214fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    Mutex::Autolock autoLock(mLock);
215fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
216fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<ABuffer> buffer;
217fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    int32_t extSeqNo;
218fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    while (!mPackets.empty()) {
219fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        buffer = *mPackets.begin();
220fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        extSeqNo = buffer->int32Data();
221fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
222fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (mLastDequeuedExtSeqNo < 0 || extSeqNo > mLastDequeuedExtSeqNo) {
223fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            break;
224fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
225fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
226fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        // This is a retransmission of a packet we've already returned.
227fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
228fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mTotalBytesQueued -= buffer->size();
229fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        buffer.clear();
230fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        extSeqNo = -1;
231fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
232fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mPackets.erase(mPackets.begin());
233fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
234fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
235fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (mPackets.empty()) {
236fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (mFirstFailedAttemptUs < 0ll) {
237fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mFirstFailedAttemptUs = ALooper::GetNowUs();
238fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mRequestedRetransmission = false;
239fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        } else {
240fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            ALOGV("no packets available for %.2f secs",
241fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    (ALooper::GetNowUs() - mFirstFailedAttemptUs) / 1E6);
242fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
243fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
244fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return NULL;
245fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
246fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
247fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (mLastDequeuedExtSeqNo < 0 || extSeqNo == mLastDequeuedExtSeqNo + 1) {
248fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (mRequestedRetransmission) {
249fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            ALOGI("Recovered after requesting retransmission of %d",
250fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                  extSeqNo);
251fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
252fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
253fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mLastDequeuedExtSeqNo = extSeqNo;
254fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mFirstFailedAttemptUs = -1ll;
255fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mRequestedRetransmission = false;
256fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
257fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mPackets.erase(mPackets.begin());
258fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
259fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mTotalBytesQueued -= buffer->size();
260fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
261fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return buffer;
262fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
263fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
264fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (mFirstFailedAttemptUs < 0ll) {
265fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mFirstFailedAttemptUs = ALooper::GetNowUs();
266fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
267fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        ALOGI("failed to get the correct packet the first time.");
268fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return NULL;
269fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
270fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
271fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (mFirstFailedAttemptUs + 50000ll > ALooper::GetNowUs()) {
272fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        // We're willing to wait a little while to get the right packet.
273fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
274fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        if (!mRequestedRetransmission) {
275fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            ALOGI("requesting retransmission of seqNo %d",
276fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                  (mLastDequeuedExtSeqNo + 1) & 0xffff);
277fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
278fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            sp<AMessage> notify = mNotifyLost->dup();
279fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            notify->setInt32("seqNo", (mLastDequeuedExtSeqNo + 1) & 0xffff);
280fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            notify->post();
281fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
282fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mRequestedRetransmission = true;
283fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        } else {
284fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            ALOGI("still waiting for the correct packet to arrive.");
285fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
286fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
287fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        return NULL;
288fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
289fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
290fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    ALOGI("dropping packet. extSeqNo %d didn't arrive in time",
291fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mLastDequeuedExtSeqNo + 1);
292fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
293fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    // Permanent failure, we never received the packet.
294fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mLastDequeuedExtSeqNo = extSeqNo;
295fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mFirstFailedAttemptUs = -1ll;
296fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mRequestedRetransmission = false;
297fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
298fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mTotalBytesQueued -= buffer->size();
299fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
300fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mPackets.erase(mPackets.begin());
301fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
302fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    return buffer;
303fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
304fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
305fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid TunnelRenderer::onMessageReceived(const sp<AMessage> &msg) {
306fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    switch (msg->what()) {
307fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        case kWhatQueueBuffer:
308fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        {
309fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            sp<ABuffer> buffer;
310fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            CHECK(msg->findBuffer("buffer", &buffer));
311fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
312fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            queueBuffer(buffer);
313fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
314fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            if (mStreamSource == NULL) {
315fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                if (mTotalBytesQueued > 0ll) {
316fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    initPlayer();
317fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                } else {
318fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    ALOGI("Have %lld bytes queued...", mTotalBytesQueued);
319fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                }
320fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            } else {
321fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                mStreamSource->doSomeWork();
322fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            }
323fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            break;
324fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        }
325fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
326fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        default:
327fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            TRESPASS();
328fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
329fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
330fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
331fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid TunnelRenderer::initPlayer() {
332fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (mSurfaceTex == NULL) {
333fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mComposerClient = new SurfaceComposerClient;
334fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        CHECK_EQ(mComposerClient->initCheck(), (status_t)OK);
335fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
336fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        DisplayInfo info;
337fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        SurfaceComposerClient::getDisplayInfo(0, &info);
338fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        ssize_t displayWidth = info.w;
339fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        ssize_t displayHeight = info.h;
340fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
341fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mSurfaceControl =
342fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mComposerClient->createSurface(
343fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    String8("A Surface"),
344fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    displayWidth,
345fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    displayHeight,
346fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    PIXEL_FORMAT_RGB_565,
347fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber                    0);
348fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
349fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        CHECK(mSurfaceControl != NULL);
350fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        CHECK(mSurfaceControl->isValid());
351fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
352fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        SurfaceComposerClient::openGlobalTransaction();
353fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        CHECK_EQ(mSurfaceControl->setLayer(INT_MAX), (status_t)OK);
354fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        CHECK_EQ(mSurfaceControl->show(), (status_t)OK);
355fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        SurfaceComposerClient::closeGlobalTransaction();
356fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
357fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mSurface = mSurfaceControl->getSurface();
358fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        CHECK(mSurface != NULL);
359fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
360fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
361fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<IServiceManager> sm = defaultServiceManager();
362fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<IBinder> binder = sm->getService(String16("media.player"));
363fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
364fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    CHECK(service.get() != NULL);
365fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
366fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mStreamSource = new StreamSource(this);
367fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
368fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mPlayerClient = new PlayerClient;
369fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
370fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mPlayer = service->create(getpid(), mPlayerClient, 0);
371fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    CHECK(mPlayer != NULL);
372fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    CHECK_EQ(mPlayer->setDataSource(mStreamSource), (status_t)OK);
373fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
374fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mPlayer->setVideoSurfaceTexture(
375fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber            mSurfaceTex != NULL ? mSurfaceTex : mSurface->getSurfaceTexture());
376fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
377fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mPlayer->start();
378fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
379fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
380fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Hubervoid TunnelRenderer::destroyPlayer() {
381fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mStreamSource.clear();
382fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
383fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mPlayer->stop();
384fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    mPlayer.clear();
385fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
386fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    if (mSurfaceTex == NULL) {
387fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mSurface.clear();
388fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mSurfaceControl.clear();
389fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
390fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mComposerClient->dispose();
391fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber        mComposerClient.clear();
392fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber    }
393fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}
394fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
395fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber}  // namespace android
396fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96Andreas Huber
397