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