AudioRecord.cpp revision 68cbeba4e21aa53f52fb99b74dfa1910af31a3eb
1/*
2**
3** Copyright 2008, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "AudioRecord"
20
21#include <stdint.h>
22#include <sys/types.h>
23
24#include <sched.h>
25#include <sys/resource.h>
26
27#include <private/media/AudioTrackShared.h>
28
29#include <media/AudioSystem.h>
30#include <media/AudioRecord.h>
31#include <media/mediarecorder.h>
32
33#include <binder/IServiceManager.h>
34#include <utils/Log.h>
35#include <binder/Parcel.h>
36#include <binder/IPCThreadState.h>
37#include <utils/Timers.h>
38#include <utils/Atomic.h>
39
40#include <system/audio.h>
41#include <cutils/bitops.h>
42
43#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
44#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
45
46namespace android {
47// ---------------------------------------------------------------------------
48
49// static
50status_t AudioRecord::getMinFrameCount(
51        int* frameCount,
52        uint32_t sampleRate,
53        int format,
54        int channelCount)
55{
56    size_t size = 0;
57    if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &size)
58            != NO_ERROR) {
59        LOGE("AudioSystem could not query the input buffer size.");
60        return NO_INIT;
61    }
62
63    if (size == 0) {
64        LOGE("Unsupported configuration: sampleRate %d, format %d, channelCount %d",
65            sampleRate, format, channelCount);
66        return BAD_VALUE;
67    }
68
69    // We double the size of input buffer for ping pong use of record buffer.
70    size <<= 1;
71
72    if (audio_is_linear_pcm(format)) {
73        size /= channelCount * audio_bytes_per_sample(format);
74    }
75
76    *frameCount = size;
77    return NO_ERROR;
78}
79
80// ---------------------------------------------------------------------------
81
82AudioRecord::AudioRecord()
83    : mStatus(NO_INIT), mSessionId(0)
84{
85}
86
87AudioRecord::AudioRecord(
88        int inputSource,
89        uint32_t sampleRate,
90        int format,
91        uint32_t channelMask,
92        int frameCount,
93        uint32_t flags,
94        callback_t cbf,
95        void* user,
96        int notificationFrames,
97        int sessionId)
98    : mStatus(NO_INIT), mSessionId(0)
99{
100    mStatus = set(inputSource, sampleRate, format, channelMask,
101            frameCount, flags, cbf, user, notificationFrames, sessionId);
102}
103
104AudioRecord::~AudioRecord()
105{
106    if (mStatus == NO_ERROR) {
107        // Make sure that callback function exits in the case where
108        // it is looping on buffer empty condition in obtainBuffer().
109        // Otherwise the callback thread will never exit.
110        stop();
111        if (mClientRecordThread != 0) {
112            mClientRecordThread->requestExitAndWait();
113            mClientRecordThread.clear();
114        }
115        mAudioRecord.clear();
116        IPCThreadState::self()->flushCommands();
117    }
118}
119
120status_t AudioRecord::set(
121        int inputSource,
122        uint32_t sampleRate,
123        int format,
124        uint32_t channelMask,
125        int frameCount,
126        uint32_t flags,
127        callback_t cbf,
128        void* user,
129        int notificationFrames,
130        bool threadCanCallJava,
131        int sessionId)
132{
133
134    LOGV("set(): sampleRate %d, channelMask %d, frameCount %d",sampleRate, channelMask, frameCount);
135
136    AutoMutex lock(mLock);
137
138    if (mAudioRecord != 0) {
139        return INVALID_OPERATION;
140    }
141
142    if (inputSource == AUDIO_SOURCE_DEFAULT) {
143        inputSource = AUDIO_SOURCE_MIC;
144    }
145
146    if (sampleRate == 0) {
147        sampleRate = DEFAULT_SAMPLE_RATE;
148    }
149    // these below should probably come from the audioFlinger too...
150    if (format == 0) {
151        format = AUDIO_FORMAT_PCM_16_BIT;
152    }
153    // validate parameters
154    if (!audio_is_valid_format(format)) {
155        LOGE("Invalid format");
156        return BAD_VALUE;
157    }
158
159    if (!audio_is_input_channel(channelMask)) {
160        return BAD_VALUE;
161    }
162
163    int channelCount = popcount(channelMask);
164
165    audio_io_handle_t input = AudioSystem::getInput(inputSource,
166                                    sampleRate, format, channelMask, (audio_in_acoustics_t)flags);
167    if (input == 0) {
168        LOGE("Could not get audio input for record source %d", inputSource);
169        return BAD_VALUE;
170    }
171
172    // validate framecount
173    int minFrameCount = 0;
174    status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelCount);
175    if (status != NO_ERROR) {
176        return status;
177    }
178    LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
179
180    if (frameCount == 0) {
181        frameCount = minFrameCount;
182    } else if (frameCount < minFrameCount) {
183        return BAD_VALUE;
184    }
185
186    if (notificationFrames == 0) {
187        notificationFrames = frameCount/2;
188    }
189
190    mSessionId = sessionId;
191
192    // create the IAudioRecord
193    status = openRecord_l(sampleRate, format, channelMask,
194                        frameCount, flags, input);
195    if (status != NO_ERROR) {
196        return status;
197    }
198
199    if (cbf != 0) {
200        mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava);
201        if (mClientRecordThread == 0) {
202            return NO_INIT;
203        }
204    }
205
206    mStatus = NO_ERROR;
207
208    mFormat = format;
209    // Update buffer size in case it has been limited by AudioFlinger during track creation
210    mFrameCount = mCblk->frameCount;
211    mChannelCount = (uint8_t)channelCount;
212    mChannelMask = channelMask;
213    mActive = 0;
214    mCbf = cbf;
215    mNotificationFrames = notificationFrames;
216    mRemainingFrames = notificationFrames;
217    mUserData = user;
218    // TODO: add audio hardware input latency here
219    mLatency = (1000*mFrameCount) / sampleRate;
220    mMarkerPosition = 0;
221    mMarkerReached = false;
222    mNewPosition = 0;
223    mUpdatePeriod = 0;
224    mInputSource = (uint8_t)inputSource;
225    mFlags = flags;
226    mInput = input;
227
228    return NO_ERROR;
229}
230
231status_t AudioRecord::initCheck() const
232{
233    return mStatus;
234}
235
236// -------------------------------------------------------------------------
237
238uint32_t AudioRecord::latency() const
239{
240    return mLatency;
241}
242
243int AudioRecord::format() const
244{
245    return mFormat;
246}
247
248int AudioRecord::channelCount() const
249{
250    return mChannelCount;
251}
252
253uint32_t AudioRecord::frameCount() const
254{
255    return mFrameCount;
256}
257
258int AudioRecord::frameSize() const
259{
260    if (audio_is_linear_pcm(mFormat)) {
261        return channelCount()*audio_bytes_per_sample(mFormat);
262    } else {
263        return sizeof(uint8_t);
264    }
265}
266
267int AudioRecord::inputSource() const
268{
269    return (int)mInputSource;
270}
271
272// -------------------------------------------------------------------------
273
274status_t AudioRecord::start()
275{
276    status_t ret = NO_ERROR;
277    sp<ClientRecordThread> t = mClientRecordThread;
278
279    LOGV("start");
280
281    if (t != 0) {
282        if (t->exitPending()) {
283            if (t->requestExitAndWait() == WOULD_BLOCK) {
284                LOGE("AudioRecord::start called from thread");
285                return WOULD_BLOCK;
286            }
287        }
288        t->mLock.lock();
289     }
290
291    AutoMutex lock(mLock);
292    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
293    // while we are accessing the cblk
294    sp <IAudioRecord> audioRecord = mAudioRecord;
295    sp <IMemory> iMem = mCblkMemory;
296    audio_track_cblk_t* cblk = mCblk;
297    if (mActive == 0) {
298        mActive = 1;
299
300        cblk->lock.lock();
301        if (!(cblk->flags & CBLK_INVALID_MSK)) {
302            cblk->lock.unlock();
303            ret = mAudioRecord->start();
304            cblk->lock.lock();
305            if (ret == DEAD_OBJECT) {
306                android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
307            }
308        }
309        if (cblk->flags & CBLK_INVALID_MSK) {
310            ret = restoreRecord_l(cblk);
311        }
312        cblk->lock.unlock();
313        if (ret == NO_ERROR) {
314            mNewPosition = cblk->user + mUpdatePeriod;
315            cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
316            cblk->waitTimeMs = 0;
317            if (t != 0) {
318               t->run("ClientRecordThread", ANDROID_PRIORITY_AUDIO);
319            } else {
320                setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
321            }
322        } else {
323            mActive = 0;
324        }
325    }
326
327    if (t != 0) {
328        t->mLock.unlock();
329    }
330
331    return ret;
332}
333
334status_t AudioRecord::stop()
335{
336    sp<ClientRecordThread> t = mClientRecordThread;
337
338    LOGV("stop");
339
340    if (t != 0) {
341        t->mLock.lock();
342    }
343
344    AutoMutex lock(mLock);
345    if (mActive == 1) {
346        mActive = 0;
347        mCblk->cv.signal();
348        mAudioRecord->stop();
349        // the record head position will reset to 0, so if a marker is set, we need
350        // to activate it again
351        mMarkerReached = false;
352        if (t != 0) {
353            t->requestExit();
354        } else {
355            setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
356        }
357    }
358
359    if (t != 0) {
360        t->mLock.unlock();
361    }
362
363    return NO_ERROR;
364}
365
366bool AudioRecord::stopped() const
367{
368    return !mActive;
369}
370
371uint32_t AudioRecord::getSampleRate()
372{
373    AutoMutex lock(mLock);
374    return mCblk->sampleRate;
375}
376
377status_t AudioRecord::setMarkerPosition(uint32_t marker)
378{
379    if (mCbf == 0) return INVALID_OPERATION;
380
381    mMarkerPosition = marker;
382    mMarkerReached = false;
383
384    return NO_ERROR;
385}
386
387status_t AudioRecord::getMarkerPosition(uint32_t *marker)
388{
389    if (marker == 0) return BAD_VALUE;
390
391    *marker = mMarkerPosition;
392
393    return NO_ERROR;
394}
395
396status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
397{
398    if (mCbf == 0) return INVALID_OPERATION;
399
400    uint32_t curPosition;
401    getPosition(&curPosition);
402    mNewPosition = curPosition + updatePeriod;
403    mUpdatePeriod = updatePeriod;
404
405    return NO_ERROR;
406}
407
408status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod)
409{
410    if (updatePeriod == 0) return BAD_VALUE;
411
412    *updatePeriod = mUpdatePeriod;
413
414    return NO_ERROR;
415}
416
417status_t AudioRecord::getPosition(uint32_t *position)
418{
419    if (position == 0) return BAD_VALUE;
420
421    AutoMutex lock(mLock);
422    *position = mCblk->user;
423
424    return NO_ERROR;
425}
426
427unsigned int AudioRecord::getInputFramesLost()
428{
429    if (mActive)
430        return AudioSystem::getInputFramesLost(mInput);
431    else
432        return 0;
433}
434
435// -------------------------------------------------------------------------
436
437// must be called with mLock held
438status_t AudioRecord::openRecord_l(
439        uint32_t sampleRate,
440        uint32_t format,
441        uint32_t channelMask,
442        int frameCount,
443        uint32_t flags,
444        audio_io_handle_t input)
445{
446    status_t status;
447    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
448    if (audioFlinger == 0) {
449        return NO_INIT;
450    }
451
452    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input,
453                                                       sampleRate, format,
454                                                       channelMask,
455                                                       frameCount,
456                                                       ((uint16_t)flags) << 16,
457                                                       &mSessionId,
458                                                       &status);
459    if (record == 0) {
460        LOGE("AudioFlinger could not create record track, status: %d", status);
461        return status;
462    }
463    sp<IMemory> cblk = record->getCblk();
464    if (cblk == 0) {
465        LOGE("Could not get control block");
466        return NO_INIT;
467    }
468    mAudioRecord.clear();
469    mAudioRecord = record;
470    mCblkMemory.clear();
471    mCblkMemory = cblk;
472    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
473    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
474    android_atomic_and(~CBLK_DIRECTION_MSK, &mCblk->flags);
475    mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
476    mCblk->waitTimeMs = 0;
477    return NO_ERROR;
478}
479
480status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
481{
482    AutoMutex lock(mLock);
483    int active;
484    status_t result = NO_ERROR;
485    audio_track_cblk_t* cblk = mCblk;
486    uint32_t framesReq = audioBuffer->frameCount;
487    uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
488
489    audioBuffer->frameCount  = 0;
490    audioBuffer->size        = 0;
491
492    uint32_t framesReady = cblk->framesReady();
493
494    if (framesReady == 0) {
495        cblk->lock.lock();
496        goto start_loop_here;
497        while (framesReady == 0) {
498            active = mActive;
499            if (UNLIKELY(!active)) {
500                cblk->lock.unlock();
501                return NO_MORE_BUFFERS;
502            }
503            if (UNLIKELY(!waitCount)) {
504                cblk->lock.unlock();
505                return WOULD_BLOCK;
506            }
507            if (!(cblk->flags & CBLK_INVALID_MSK)) {
508                mLock.unlock();
509                result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
510                cblk->lock.unlock();
511                mLock.lock();
512                if (mActive == 0) {
513                    return status_t(STOPPED);
514                }
515                cblk->lock.lock();
516            }
517            if (cblk->flags & CBLK_INVALID_MSK) {
518                goto create_new_record;
519            }
520            if (__builtin_expect(result!=NO_ERROR, false)) {
521                cblk->waitTimeMs += waitTimeMs;
522                if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
523                    LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
524                            "user=%08x, server=%08x", cblk->user, cblk->server);
525                    cblk->lock.unlock();
526                    result = mAudioRecord->start();
527                    cblk->lock.lock();
528                    if (result == DEAD_OBJECT) {
529                        android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
530create_new_record:
531                        result = AudioRecord::restoreRecord_l(cblk);
532                    }
533                    if (result != NO_ERROR) {
534                        LOGW("obtainBuffer create Track error %d", result);
535                        cblk->lock.unlock();
536                        return result;
537                    }
538                    cblk->waitTimeMs = 0;
539                }
540                if (--waitCount == 0) {
541                    cblk->lock.unlock();
542                    return TIMED_OUT;
543                }
544            }
545            // read the server count again
546        start_loop_here:
547            framesReady = cblk->framesReady();
548        }
549        cblk->lock.unlock();
550    }
551
552    cblk->waitTimeMs = 0;
553
554    if (framesReq > framesReady) {
555        framesReq = framesReady;
556    }
557
558    uint32_t u = cblk->user;
559    uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
560
561    if (u + framesReq > bufferEnd) {
562        framesReq = bufferEnd - u;
563    }
564
565    audioBuffer->flags       = 0;
566    audioBuffer->channelCount= mChannelCount;
567    audioBuffer->format      = mFormat;
568    audioBuffer->frameCount  = framesReq;
569    audioBuffer->size        = framesReq*cblk->frameSize;
570    audioBuffer->raw         = (int8_t*)cblk->buffer(u);
571    active = mActive;
572    return active ? status_t(NO_ERROR) : status_t(STOPPED);
573}
574
575void AudioRecord::releaseBuffer(Buffer* audioBuffer)
576{
577    AutoMutex lock(mLock);
578    mCblk->stepUser(audioBuffer->frameCount);
579}
580
581audio_io_handle_t AudioRecord::getInput()
582{
583    AutoMutex lock(mLock);
584    return getInput_l();
585}
586
587// must be called with mLock held
588audio_io_handle_t AudioRecord::getInput_l()
589{
590    mInput = AudioSystem::getInput(mInputSource,
591                                mCblk->sampleRate,
592                                mFormat, mChannelMask,
593                                (audio_in_acoustics_t)mFlags);
594    return mInput;
595}
596
597int AudioRecord::getSessionId()
598{
599    return mSessionId;
600}
601
602// -------------------------------------------------------------------------
603
604ssize_t AudioRecord::read(void* buffer, size_t userSize)
605{
606    ssize_t read = 0;
607    Buffer audioBuffer;
608    int8_t *dst = static_cast<int8_t*>(buffer);
609
610    if (ssize_t(userSize) < 0) {
611        // sanity-check. user is most-likely passing an error code.
612        LOGE("AudioRecord::read(buffer=%p, size=%u (%d)",
613                buffer, userSize, userSize);
614        return BAD_VALUE;
615    }
616
617    mLock.lock();
618    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
619    // while we are accessing the cblk
620    sp <IAudioRecord> audioRecord = mAudioRecord;
621    sp <IMemory> iMem = mCblkMemory;
622    mLock.unlock();
623
624    do {
625
626        audioBuffer.frameCount = userSize/frameSize();
627
628        // By using a wait count corresponding to twice the timeout period in
629        // obtainBuffer() we give a chance to recover once for a read timeout
630        // (if media_server crashed for instance) before returning a length of
631        // 0 bytes read to the client
632        status_t err = obtainBuffer(&audioBuffer, ((2 * MAX_RUN_TIMEOUT_MS) / WAIT_PERIOD_MS));
633        if (err < 0) {
634            // out of buffers, return #bytes written
635            if (err == status_t(NO_MORE_BUFFERS))
636                break;
637            if (err == status_t(TIMED_OUT))
638                err = 0;
639            return ssize_t(err);
640        }
641
642        size_t bytesRead = audioBuffer.size;
643        memcpy(dst, audioBuffer.i8, bytesRead);
644
645        dst += bytesRead;
646        userSize -= bytesRead;
647        read += bytesRead;
648
649        releaseBuffer(&audioBuffer);
650    } while (userSize);
651
652    return read;
653}
654
655// -------------------------------------------------------------------------
656
657bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
658{
659    Buffer audioBuffer;
660    uint32_t frames = mRemainingFrames;
661    size_t readSize;
662
663    mLock.lock();
664    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
665    // while we are accessing the cblk
666    sp <IAudioRecord> audioRecord = mAudioRecord;
667    sp <IMemory> iMem = mCblkMemory;
668    audio_track_cblk_t* cblk = mCblk;
669    mLock.unlock();
670
671    // Manage marker callback
672    if (!mMarkerReached && (mMarkerPosition > 0)) {
673        if (cblk->user >= mMarkerPosition) {
674            mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition);
675            mMarkerReached = true;
676        }
677    }
678
679    // Manage new position callback
680    if (mUpdatePeriod > 0) {
681        while (cblk->user >= mNewPosition) {
682            mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition);
683            mNewPosition += mUpdatePeriod;
684        }
685    }
686
687    do {
688        audioBuffer.frameCount = frames;
689        // Calling obtainBuffer() with a wait count of 1
690        // limits wait time to WAIT_PERIOD_MS. This prevents from being
691        // stuck here not being able to handle timed events (position, markers).
692        status_t err = obtainBuffer(&audioBuffer, 1);
693        if (err < NO_ERROR) {
694            if (err != TIMED_OUT) {
695                LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
696                return false;
697            }
698            break;
699        }
700        if (err == status_t(STOPPED)) return false;
701
702        size_t reqSize = audioBuffer.size;
703        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
704        readSize = audioBuffer.size;
705
706        // Sanity check on returned size
707        if (ssize_t(readSize) <= 0) {
708            // The callback is done filling buffers
709            // Keep this thread going to handle timed events and
710            // still try to get more data in intervals of WAIT_PERIOD_MS
711            // but don't just loop and block the CPU, so wait
712            usleep(WAIT_PERIOD_MS*1000);
713            break;
714        }
715        if (readSize > reqSize) readSize = reqSize;
716
717        audioBuffer.size = readSize;
718        audioBuffer.frameCount = readSize/frameSize();
719        frames -= audioBuffer.frameCount;
720
721        releaseBuffer(&audioBuffer);
722
723    } while (frames);
724
725
726    // Manage overrun callback
727    if (mActive && (cblk->framesAvailable() == 0)) {
728        LOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
729        if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) {
730            mCbf(EVENT_OVERRUN, mUserData, 0);
731        }
732    }
733
734    if (frames == 0) {
735        mRemainingFrames = mNotificationFrames;
736    } else {
737        mRemainingFrames = frames;
738    }
739    return true;
740}
741
742// must be called with mLock and cblk.lock held. Callers must also hold strong references on
743// the IAudioRecord and IMemory in case they are recreated here.
744// If the IAudioRecord is successfully restored, the cblk pointer is updated
745status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
746{
747    status_t result;
748
749    if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) {
750        LOGW("dead IAudioRecord, creating a new one");
751        // signal old cblk condition so that other threads waiting for available buffers stop
752        // waiting now
753        cblk->cv.broadcast();
754        cblk->lock.unlock();
755
756        // if the new IAudioRecord is created, openRecord_l() will modify the
757        // following member variables: mAudioRecord, mCblkMemory and mCblk.
758        // It will also delete the strong references on previous IAudioRecord and IMemory
759        result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask,
760                mFrameCount, mFlags, getInput_l());
761        if (result == NO_ERROR) {
762            result = mAudioRecord->start();
763        }
764        if (result != NO_ERROR) {
765            mActive = false;
766        }
767
768        // signal old cblk condition for other threads waiting for restore completion
769        android_atomic_or(CBLK_RESTORED_ON, &cblk->flags);
770        cblk->cv.broadcast();
771    } else {
772        if (!(cblk->flags & CBLK_RESTORED_MSK)) {
773            LOGW("dead IAudioRecord, waiting for a new one to be created");
774            mLock.unlock();
775            result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS));
776            cblk->lock.unlock();
777            mLock.lock();
778        } else {
779            LOGW("dead IAudioRecord, already restored");
780            result = NO_ERROR;
781            cblk->lock.unlock();
782        }
783        if (result != NO_ERROR || mActive == 0) {
784            result = status_t(STOPPED);
785        }
786    }
787    LOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x",
788         result, mActive, mCblk, cblk, mCblk->flags, cblk->flags);
789
790    if (result == NO_ERROR) {
791        // from now on we switch to the newly created cblk
792        cblk = mCblk;
793    }
794    cblk->lock.lock();
795
796    LOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result);
797
798    return result;
799}
800
801// =========================================================================
802
803AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava)
804    : Thread(bCanCallJava), mReceiver(receiver)
805{
806}
807
808bool AudioRecord::ClientRecordThread::threadLoop()
809{
810    return mReceiver.processAudioBuffer(this);
811}
812
813// -------------------------------------------------------------------------
814
815}; // namespace android
816
817