1f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten/*
2f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * Copyright (C) 2014 The Android Open Source Project
3f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten *
4f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
5f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * you may not use this file except in compliance with the License.
6f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * You may obtain a copy of the License at
7f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten *
8f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
9f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten *
10f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * Unless required by applicable law or agreed to in writing, software
11f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
12f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * See the License for the specific language governing permissions and
14f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten * limitations under the License.
15f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten */
16f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
17f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#define LOG_TAG "FastCapture"
18f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten//#define LOG_NDEBUG 0
19f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
20f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#define ATRACE_TAG ATRACE_TAG_AUDIO
21f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
22f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include "Configuration.h"
23f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include <linux/futex.h>
24f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include <sys/syscall.h>
25f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include <media/AudioBufferProvider.h>
26f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include <utils/Log.h>
27f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include <utils/Trace.h>
28f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten#include "FastCapture.h"
29f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
30f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastennamespace android {
31f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
32f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten/*static*/ const FastCaptureState FastCapture::initial;
33f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
34f91df1b368a140abd37c80b204bd48d78778cc43Glenn KastenFastCapture::FastCapture() : FastThread(),
35f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    inputSource(NULL), inputSourceGen(0), pipeSink(NULL), pipeSinkGen(0),
36f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    readBuffer(NULL), readBufferState(-1), format(Format_Invalid), sampleRate(0),
37f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    // dummyDumpState
38f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    totalNativeFramesRead(0)
39f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{
40f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    previous = &initial;
41f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    current = &initial;
42f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
43f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    mDummyDumpState = &dummyDumpState;
44f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten}
45f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
46f91df1b368a140abd37c80b204bd48d78778cc43Glenn KastenFastCapture::~FastCapture()
47f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{
48f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten}
49f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
50f91df1b368a140abd37c80b204bd48d78778cc43Glenn KastenFastCaptureStateQueue* FastCapture::sq()
51f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{
52f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    return &mSQ;
53f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten}
54f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
55f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenconst FastThreadState *FastCapture::poll()
56f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{
57f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    return mSQ.poll();
58f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten}
59f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
60f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenvoid FastCapture::setLog(NBLog::Writer *logWriter __unused)
61f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{
62f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten}
63f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
64f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenvoid FastCapture::onIdle()
65f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{
66f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    preIdle = *(const FastCaptureState *)current;
67f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    current = &preIdle;
68f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten}
69f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
70f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenvoid FastCapture::onExit()
71f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{
72f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    delete[] readBuffer;
73f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten}
74f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
75f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenbool FastCapture::isSubClassCommand(FastThreadState::Command command)
76f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{
77f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    switch ((FastCaptureState::Command) command) {
78f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    case FastCaptureState::READ:
79f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    case FastCaptureState::WRITE:
80f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    case FastCaptureState::READ_WRITE:
81f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        return true;
82f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    default:
83f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        return false;
84f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    }
85f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten}
86f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
87f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenvoid FastCapture::onStateChange()
88f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{
89f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    const FastCaptureState * const current = (const FastCaptureState *) this->current;
90f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    const FastCaptureState * const previous = (const FastCaptureState *) this->previous;
91f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) this->dumpState;
92f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    const size_t frameCount = current->mFrameCount;
93f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
94f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    bool eitherChanged = false;
95f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
96f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    // check for change in input HAL configuration
97f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    NBAIO_Format previousFormat = format;
98f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    if (current->mInputSourceGen != inputSourceGen) {
99f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        inputSource = current->mInputSource;
100f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        inputSourceGen = current->mInputSourceGen;
101f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        if (inputSource == NULL) {
102f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            format = Format_Invalid;
103f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            sampleRate = 0;
104f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        } else {
105f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            format = inputSource->format();
106f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            sampleRate = Format_sampleRate(format);
107f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            unsigned channelCount = Format_channelCount(format);
108f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            ALOG_ASSERT(channelCount == 1 || channelCount == 2);
109f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        }
110f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        dumpState->mSampleRate = sampleRate;
111f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        eitherChanged = true;
112f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    }
113f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
114f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    // check for change in pipe
115f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    if (current->mPipeSinkGen != pipeSinkGen) {
116f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        pipeSink = current->mPipeSink;
117f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        pipeSinkGen = current->mPipeSinkGen;
118f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        eitherChanged = true;
119f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    }
120f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
121f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    // input source and pipe sink must be compatible
122f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    if (eitherChanged && inputSource != NULL && pipeSink != NULL) {
123f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        ALOG_ASSERT(Format_isEqual(format, pipeSink->format()));
124f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    }
125f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
126f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    if ((!Format_isEqual(format, previousFormat)) || (frameCount != previous->mFrameCount)) {
127f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        // FIXME to avoid priority inversion, don't delete here
128f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        delete[] readBuffer;
129f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        readBuffer = NULL;
130f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        if (frameCount > 0 && sampleRate > 0) {
131f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            // FIXME new may block for unbounded time at internal mutex of the heap
132f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            //       implementation; it would be better to have normal capture thread allocate for
133f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            //       us to avoid blocking here and to prevent possible priority inversion
134f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            unsigned channelCount = Format_channelCount(format);
135f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            // FIXME frameSize
136f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            readBuffer = new short[frameCount * channelCount];
137f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            periodNs = (frameCount * 1000000000LL) / sampleRate;    // 1.00
138f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            underrunNs = (frameCount * 1750000000LL) / sampleRate;  // 1.75
139f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            overrunNs = (frameCount * 500000000LL) / sampleRate;    // 0.50
140f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            forceNs = (frameCount * 950000000LL) / sampleRate;      // 0.95
141f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            warmupNs = (frameCount * 500000000LL) / sampleRate;     // 0.50
142f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        } else {
143f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            periodNs = 0;
144f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            underrunNs = 0;
145f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            overrunNs = 0;
146f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            forceNs = 0;
147f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            warmupNs = 0;
148f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        }
149f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        readBufferState = -1;
150f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        dumpState->mFrameCount = frameCount;
151f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    }
152f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
153f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten}
154f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
155f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kastenvoid FastCapture::onWork()
156f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{
157f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    const FastCaptureState * const current = (const FastCaptureState *) this->current;
158f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) this->dumpState;
159f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    const FastCaptureState::Command command = this->command;
160f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    const size_t frameCount = current->mFrameCount;
161f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
162f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    if ((command & FastCaptureState::READ) /*&& isWarm*/) {
163f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        ALOG_ASSERT(inputSource != NULL);
164f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        ALOG_ASSERT(readBuffer != NULL);
165f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        dumpState->mReadSequence++;
166f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        ATRACE_BEGIN("read");
167f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        ssize_t framesRead = inputSource->read(readBuffer, frameCount,
168f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten                AudioBufferProvider::kInvalidPTS);
169f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        ATRACE_END();
170f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        dumpState->mReadSequence++;
171f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        if (framesRead >= 0) {
172f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            LOG_ALWAYS_FATAL_IF((size_t) framesRead > frameCount);
173f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            totalNativeFramesRead += framesRead;
174f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            dumpState->mFramesRead = totalNativeFramesRead;
175f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            readBufferState = framesRead;
176f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        } else {
177f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            dumpState->mReadErrors++;
178f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            readBufferState = 0;
179f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        }
180f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        // FIXME rename to attemptedIO
181f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        attemptedWrite = true;
182f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    }
183f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
184f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    if (command & FastCaptureState::WRITE) {
185f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        ALOG_ASSERT(pipeSink != NULL);
186f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        ALOG_ASSERT(readBuffer != NULL);
187f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        if (readBufferState < 0) {
188f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            unsigned channelCount = Format_channelCount(format);
189f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            // FIXME frameSize
190f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            memset(readBuffer, 0, frameCount * channelCount * sizeof(short));
191f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            readBufferState = frameCount;
192f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        }
193f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        if (readBufferState > 0) {
194f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            ssize_t framesWritten = pipeSink->write(readBuffer, readBufferState);
195f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            // FIXME This supports at most one fast capture client.
196f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            //       To handle multiple clients this could be converted to an array,
197f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            //       or with a lot more work the control block could be shared by all clients.
198f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            audio_track_cblk_t* cblk = current->mCblk;
199f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            if (cblk != NULL && framesWritten > 0) {
200f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten                int32_t rear = cblk->u.mStreaming.mRear;
201f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten                android_atomic_release_store(framesWritten + rear, &cblk->u.mStreaming.mRear);
202f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten                cblk->mServer += framesWritten;
203f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten                int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
204f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten                if (!(old & CBLK_FUTEX_WAKE)) {
205f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten                    // client is never in server process, so don't use FUTEX_WAKE_PRIVATE
206f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten                    (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, 1);
207f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten                }
208f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten            }
209f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten        }
210f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    }
211f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten}
212f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
213f91df1b368a140abd37c80b204bd48d78778cc43Glenn KastenFastCaptureDumpState::FastCaptureDumpState() : FastThreadDumpState(),
214f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten    mReadSequence(0), mFramesRead(0), mReadErrors(0), mSampleRate(0), mFrameCount(0)
215f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{
216f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten}
217f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
218f91df1b368a140abd37c80b204bd48d78778cc43Glenn KastenFastCaptureDumpState::~FastCaptureDumpState()
219f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten{
220f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten}
221f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten
222f91df1b368a140abd37c80b204bd48d78778cc43Glenn Kasten}   // namespace android
223