1 /* //device/include/server/AudioFlinger/AudioFlinger.h 2 ** 3 ** Copyright 2007, 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 #ifndef ANDROID_AUDIO_FLINGER_H 19 #define ANDROID_AUDIO_FLINGER_H 20 21 #include <stdint.h> 22 #include <sys/types.h> 23 24 #include <media/IAudioFlinger.h> 25 #include <media/IAudioFlingerClient.h> 26 #include <media/IAudioTrack.h> 27 #include <media/IAudioRecord.h> 28 #include <media/AudioTrack.h> 29 30 #include <utils/Atomic.h> 31 #include <utils/Errors.h> 32 #include <utils/threads.h> 33 #include <binder/MemoryDealer.h> 34 #include <utils/SortedVector.h> 35 #include <utils/Vector.h> 36 37 #include <hardware_legacy/AudioHardwareInterface.h> 38 39 #include "AudioBufferProvider.h" 40 41 namespace android { 42 43 class audio_track_cblk_t; 44 class AudioMixer; 45 class AudioBuffer; 46 class AudioResampler; 47 48 49 // ---------------------------------------------------------------------------- 50 51 #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) 52 #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) 53 54 55 // ---------------------------------------------------------------------------- 56 57 static const nsecs_t kStandbyTimeInNsecs = seconds(3); 58 59 class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient 60 { 61 public: 62 static void instantiate(); 63 64 virtual status_t dump(int fd, const Vector<String16>& args); 65 66 // IAudioFlinger interface 67 virtual sp<IAudioTrack> createTrack( 68 pid_t pid, 69 int streamType, 70 uint32_t sampleRate, 71 int format, 72 int channelCount, 73 int frameCount, 74 uint32_t flags, 75 const sp<IMemory>& sharedBuffer, 76 int output, 77 status_t *status); 78 79 virtual uint32_t sampleRate(int output) const; 80 virtual int channelCount(int output) const; 81 virtual int format(int output) const; 82 virtual size_t frameCount(int output) const; 83 virtual uint32_t latency(int output) const; 84 85 virtual status_t setMasterVolume(float value); 86 virtual status_t setMasterMute(bool muted); 87 88 virtual float masterVolume() const; 89 virtual bool masterMute() const; 90 91 virtual status_t setStreamVolume(int stream, float value, int output); 92 virtual status_t setStreamMute(int stream, bool muted); 93 94 virtual float streamVolume(int stream, int output) const; 95 virtual bool streamMute(int stream) const; 96 97 virtual status_t setMode(int mode); 98 99 virtual status_t setMicMute(bool state); 100 virtual bool getMicMute() const; 101 102 virtual bool isMusicActive() const; 103 104 virtual status_t setParameters(int ioHandle, const String8& keyValuePairs); 105 virtual String8 getParameters(int ioHandle, const String8& keys); 106 107 virtual void registerClient(const sp<IAudioFlingerClient>& client); 108 109 virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount); 110 111 virtual int openOutput(uint32_t *pDevices, 112 uint32_t *pSamplingRate, 113 uint32_t *pFormat, 114 uint32_t *pChannels, 115 uint32_t *pLatencyMs, 116 uint32_t flags); 117 118 virtual int openDuplicateOutput(int output1, int output2); 119 120 virtual status_t closeOutput(int output); 121 122 virtual status_t suspendOutput(int output); 123 124 virtual status_t restoreOutput(int output); 125 126 virtual int openInput(uint32_t *pDevices, 127 uint32_t *pSamplingRate, 128 uint32_t *pFormat, 129 uint32_t *pChannels, 130 uint32_t acoustics); 131 132 virtual status_t closeInput(int input); 133 134 virtual status_t setStreamOutput(uint32_t stream, int output); 135 136 virtual status_t setVoiceVolume(float volume); 137 138 // IBinder::DeathRecipient 139 virtual void binderDied(const wp<IBinder>& who); 140 141 enum hardware_call_state { 142 AUDIO_HW_IDLE = 0, 143 AUDIO_HW_INIT, 144 AUDIO_HW_OUTPUT_OPEN, 145 AUDIO_HW_OUTPUT_CLOSE, 146 AUDIO_HW_INPUT_OPEN, 147 AUDIO_HW_INPUT_CLOSE, 148 AUDIO_HW_STANDBY, 149 AUDIO_HW_SET_MASTER_VOLUME, 150 AUDIO_HW_GET_ROUTING, 151 AUDIO_HW_SET_ROUTING, 152 AUDIO_HW_GET_MODE, 153 AUDIO_HW_SET_MODE, 154 AUDIO_HW_GET_MIC_MUTE, 155 AUDIO_HW_SET_MIC_MUTE, 156 AUDIO_SET_VOICE_VOLUME, 157 AUDIO_SET_PARAMETER, 158 }; 159 160 // record interface 161 virtual sp<IAudioRecord> openRecord( 162 pid_t pid, 163 int input, 164 uint32_t sampleRate, 165 int format, 166 int channelCount, 167 int frameCount, 168 uint32_t flags, 169 status_t *status); 170 171 virtual status_t onTransact( 172 uint32_t code, 173 const Parcel& data, 174 Parcel* reply, 175 uint32_t flags); 176 177 private: 178 AudioFlinger(); 179 virtual ~AudioFlinger(); 180 181 182 // Internal dump utilites. 183 status_t dumpPermissionDenial(int fd, const Vector<String16>& args); 184 status_t dumpClients(int fd, const Vector<String16>& args); 185 status_t dumpInternals(int fd, const Vector<String16>& args); 186 187 // --- Client --- 188 class Client : public RefBase { 189 public: 190 Client(const sp<AudioFlinger>& audioFlinger, pid_t pid); 191 virtual ~Client(); 192 const sp<MemoryDealer>& heap() const; pid()193 pid_t pid() const { return mPid; } audioFlinger()194 sp<AudioFlinger> audioFlinger() { return mAudioFlinger; } 195 196 private: 197 Client(const Client&); 198 Client& operator = (const Client&); 199 sp<AudioFlinger> mAudioFlinger; 200 sp<MemoryDealer> mMemoryDealer; 201 pid_t mPid; 202 }; 203 204 205 class TrackHandle; 206 class RecordHandle; 207 class RecordThread; 208 class PlaybackThread; 209 class MixerThread; 210 class DirectOutputThread; 211 class Track; 212 class RecordTrack; 213 214 class ThreadBase : public Thread { 215 public: 216 ThreadBase (const sp<AudioFlinger>& audioFlinger); 217 virtual ~ThreadBase(); 218 219 status_t dumpBase(int fd, const Vector<String16>& args); 220 221 // base for record and playback 222 class TrackBase : public AudioBufferProvider, public RefBase { 223 224 public: 225 enum track_state { 226 IDLE, 227 TERMINATED, 228 STOPPED, 229 RESUMING, 230 ACTIVE, 231 PAUSING, 232 PAUSED 233 }; 234 235 enum track_flags { 236 STEPSERVER_FAILED = 0x01, // StepServer could not acquire cblk->lock mutex 237 SYSTEM_FLAGS_MASK = 0x0000ffffUL, 238 // The upper 16 bits are used for track-specific flags. 239 }; 240 241 TrackBase(const wp<ThreadBase>& thread, 242 const sp<Client>& client, 243 uint32_t sampleRate, 244 int format, 245 int channelCount, 246 int frameCount, 247 uint32_t flags, 248 const sp<IMemory>& sharedBuffer); 249 ~TrackBase(); 250 251 virtual status_t start() = 0; 252 virtual void stop() = 0; 253 sp<IMemory> getCblk() const; cblk()254 audio_track_cblk_t* cblk() const { return mCblk; } 255 256 protected: 257 friend class ThreadBase; 258 friend class RecordHandle; 259 friend class PlaybackThread; 260 friend class RecordThread; 261 friend class MixerThread; 262 friend class DirectOutputThread; 263 264 TrackBase(const TrackBase&); 265 TrackBase& operator = (const TrackBase&); 266 267 virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0; 268 virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); 269 format()270 int format() const { 271 return mFormat; 272 } 273 274 int channelCount() const ; 275 276 int sampleRate() const; 277 278 void* getBuffer(uint32_t offset, uint32_t frames) const; 279 isStopped()280 bool isStopped() const { 281 return mState == STOPPED; 282 } 283 isTerminated()284 bool isTerminated() const { 285 return mState == TERMINATED; 286 } 287 288 bool step(); 289 void reset(); 290 291 wp<ThreadBase> mThread; 292 sp<Client> mClient; 293 sp<IMemory> mCblkMemory; 294 audio_track_cblk_t* mCblk; 295 void* mBuffer; 296 void* mBufferEnd; 297 uint32_t mFrameCount; 298 // we don't really need a lock for these 299 int mState; 300 int mClientTid; 301 uint8_t mFormat; 302 uint32_t mFlags; 303 }; 304 305 class ConfigEvent { 306 public: ConfigEvent()307 ConfigEvent() : mEvent(0), mParam(0) {} 308 309 int mEvent; 310 int mParam; 311 }; 312 313 uint32_t sampleRate() const; 314 int channelCount() const; 315 int format() const; 316 size_t frameCount() const; wakeUp()317 void wakeUp() { mWaitWorkCV.broadcast(); } 318 void exit(); 319 virtual bool checkForNewParameters_l() = 0; 320 virtual status_t setParameters(const String8& keyValuePairs); 321 virtual String8 getParameters(const String8& keys) = 0; 322 virtual void audioConfigChanged(int event, int param = 0) = 0; 323 void sendConfigEvent(int event, int param = 0); 324 void sendConfigEvent_l(int event, int param = 0); 325 void processConfigEvents(); 326 327 mutable Mutex mLock; 328 329 protected: 330 331 friend class Track; 332 friend class TrackBase; 333 friend class PlaybackThread; 334 friend class MixerThread; 335 friend class DirectOutputThread; 336 friend class DuplicatingThread; 337 friend class RecordThread; 338 friend class RecordTrack; 339 340 Condition mWaitWorkCV; 341 sp<AudioFlinger> mAudioFlinger; 342 uint32_t mSampleRate; 343 size_t mFrameCount; 344 int mChannelCount; 345 int mFormat; 346 uint32_t mFrameSize; 347 Condition mParamCond; 348 Vector<String8> mNewParameters; 349 status_t mParamStatus; 350 Vector<ConfigEvent *> mConfigEvents; 351 bool mStandby; 352 }; 353 354 // --- PlaybackThread --- 355 class PlaybackThread : public ThreadBase { 356 public: 357 358 enum type { 359 MIXER, 360 DIRECT, 361 DUPLICATING 362 }; 363 364 // playback track 365 class Track : public TrackBase { 366 public: 367 Track( const wp<ThreadBase>& thread, 368 const sp<Client>& client, 369 int streamType, 370 uint32_t sampleRate, 371 int format, 372 int channelCount, 373 int frameCount, 374 const sp<IMemory>& sharedBuffer); 375 ~Track(); 376 377 void dump(char* buffer, size_t size); 378 virtual status_t start(); 379 virtual void stop(); 380 void pause(); 381 382 void flush(); 383 void destroy(); 384 void mute(bool); 385 void setVolume(float left, float right); name()386 int name() const { 387 return mName; 388 } 389 type()390 int type() const { 391 return mStreamType; 392 } 393 394 395 protected: 396 friend class ThreadBase; 397 friend class AudioFlinger; 398 friend class TrackHandle; 399 friend class PlaybackThread; 400 friend class MixerThread; 401 friend class DirectOutputThread; 402 403 Track(const Track&); 404 Track& operator = (const Track&); 405 406 virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); isMuted()407 bool isMuted() { return mMute; } isPausing()408 bool isPausing() const { 409 return mState == PAUSING; 410 } isPaused()411 bool isPaused() const { 412 return mState == PAUSED; 413 } 414 bool isReady() const; setPaused()415 void setPaused() { mState = PAUSED; } 416 void reset(); 417 418 // we don't really need a lock for these 419 float mVolume[2]; 420 volatile bool mMute; 421 // FILLED state is used for suppressing volume ramp at begin of playing 422 enum {FS_FILLING, FS_FILLED, FS_ACTIVE}; 423 mutable uint8_t mFillingUpStatus; 424 int8_t mRetryCount; 425 sp<IMemory> mSharedBuffer; 426 bool mResetDone; 427 int mStreamType; 428 int mName; 429 }; // end of Track 430 431 432 // playback track 433 class OutputTrack : public Track { 434 public: 435 436 class Buffer: public AudioBufferProvider::Buffer { 437 public: 438 int16_t *mBuffer; 439 }; 440 441 OutputTrack( const wp<ThreadBase>& thread, 442 uint32_t sampleRate, 443 int format, 444 int channelCount, 445 int frameCount); 446 ~OutputTrack(); 447 448 virtual status_t start(); 449 virtual void stop(); 450 bool write(int16_t* data, uint32_t frames); bufferQueueEmpty()451 bool bufferQueueEmpty() { return (mBufferQueue.size() == 0) ? true : false; } isActive()452 bool isActive() { return mActive; } thread()453 wp<ThreadBase>& thread() { return mThread; } 454 455 private: 456 457 status_t obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs); 458 void clearBufferQueue(); 459 460 // Maximum number of pending buffers allocated by OutputTrack::write() 461 static const uint8_t kMaxOverFlowBuffers = 3; 462 463 Vector < Buffer* > mBufferQueue; 464 AudioBufferProvider::Buffer mOutBuffer; 465 uint32_t mWaitTimeMs; 466 bool mActive; 467 468 }; // end of OutputTrack 469 470 PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); 471 virtual ~PlaybackThread(); 472 473 virtual status_t dump(int fd, const Vector<String16>& args); 474 475 // Thread virtuals 476 virtual status_t readyToRun(); 477 virtual void onFirstRef(); 478 479 virtual uint32_t latency() const; 480 481 virtual status_t setMasterVolume(float value); 482 virtual status_t setMasterMute(bool muted); 483 484 virtual float masterVolume() const; 485 virtual bool masterMute() const; 486 487 virtual status_t setStreamVolume(int stream, float value); 488 virtual status_t setStreamMute(int stream, bool muted); 489 490 virtual float streamVolume(int stream) const; 491 virtual bool streamMute(int stream) const; 492 493 bool isMusicActive() const; 494 495 sp<Track> createTrack_l( 496 const sp<AudioFlinger::Client>& client, 497 int streamType, 498 uint32_t sampleRate, 499 int format, 500 int channelCount, 501 int frameCount, 502 const sp<IMemory>& sharedBuffer, 503 status_t *status); 504 getOutput()505 AudioStreamOut* getOutput() { return mOutput; } 506 type()507 virtual int type() const { return mType; } suspend()508 void suspend() { mSuspended++; } restore()509 void restore() { if (mSuspended) mSuspended--; } 510 virtual String8 getParameters(const String8& keys); 511 virtual void audioConfigChanged(int event, int param = 0); 512 513 struct stream_type_t { stream_type_tstream_type_t514 stream_type_t() 515 : volume(1.0f), 516 mute(false) 517 { 518 } 519 float volume; 520 bool mute; 521 }; 522 523 protected: 524 int mType; 525 int16_t* mMixBuffer; 526 int mSuspended; 527 int mBytesWritten; 528 bool mMasterMute; 529 SortedVector< wp<Track> > mActiveTracks; 530 531 virtual int getTrackName_l() = 0; 532 virtual void deleteTrackName_l(int name) = 0; 533 virtual uint32_t getMaxBufferRecoveryInUsecs() = 0; 534 535 private: 536 537 friend class AudioFlinger; 538 friend class OutputTrack; 539 friend class Track; 540 friend class TrackBase; 541 friend class MixerThread; 542 friend class DirectOutputThread; 543 friend class DuplicatingThread; 544 545 PlaybackThread(const Client&); 546 PlaybackThread& operator = (const PlaybackThread&); 547 548 status_t addTrack_l(const sp<Track>& track); 549 void destroyTrack_l(const sp<Track>& track); 550 551 void readOutputParameters(); 552 553 virtual status_t dumpInternals(int fd, const Vector<String16>& args); 554 status_t dumpTracks(int fd, const Vector<String16>& args); 555 556 SortedVector< sp<Track> > mTracks; 557 // mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread 558 stream_type_t mStreamTypes[AudioSystem::NUM_STREAM_TYPES + 1]; 559 AudioStreamOut* mOutput; 560 float mMasterVolume; 561 nsecs_t mLastWriteTime; 562 int mNumWrites; 563 int mNumDelayedWrites; 564 bool mInWrite; 565 int mMinBytesToWrite; 566 }; 567 568 class MixerThread : public PlaybackThread { 569 public: 570 MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); 571 virtual ~MixerThread(); 572 573 // Thread virtuals 574 virtual bool threadLoop(); 575 576 void getTracks(SortedVector < sp<Track> >& tracks, 577 SortedVector < wp<Track> >& activeTracks, 578 int streamType); 579 void putTracks(SortedVector < sp<Track> >& tracks, 580 SortedVector < wp<Track> >& activeTracks); 581 virtual bool checkForNewParameters_l(); 582 virtual status_t dumpInternals(int fd, const Vector<String16>& args); 583 584 protected: 585 size_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove); 586 virtual int getTrackName_l(); 587 virtual void deleteTrackName_l(int name); 588 virtual uint32_t getMaxBufferRecoveryInUsecs(); 589 590 AudioMixer* mAudioMixer; 591 }; 592 593 class DirectOutputThread : public PlaybackThread { 594 public: 595 596 DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); 597 ~DirectOutputThread(); 598 599 // Thread virtuals 600 virtual bool threadLoop(); 601 602 virtual bool checkForNewParameters_l(); 603 604 protected: 605 virtual int getTrackName_l(); 606 virtual void deleteTrackName_l(int name); 607 virtual uint32_t getMaxBufferRecoveryInUsecs(); 608 609 private: 610 float mLeftVolume; 611 float mRightVolume; 612 }; 613 614 class DuplicatingThread : public MixerThread { 615 public: 616 DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread); 617 ~DuplicatingThread(); 618 619 // Thread virtuals 620 virtual bool threadLoop(); 621 void addOutputTrack(MixerThread* thread); 622 void removeOutputTrack(MixerThread* thread); 623 624 private: 625 SortedVector < sp<OutputTrack> > mOutputTracks; 626 }; 627 628 PlaybackThread *checkPlaybackThread_l(int output) const; 629 MixerThread *checkMixerThread_l(int output) const; 630 RecordThread *checkRecordThread_l(int input) const; streamVolumeInternal(int stream)631 float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; } 632 void audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2); 633 634 friend class AudioBuffer; 635 636 class TrackHandle : public android::BnAudioTrack { 637 public: 638 TrackHandle(const sp<PlaybackThread::Track>& track); 639 virtual ~TrackHandle(); 640 virtual status_t start(); 641 virtual void stop(); 642 virtual void flush(); 643 virtual void mute(bool); 644 virtual void pause(); 645 virtual void setVolume(float left, float right); 646 virtual sp<IMemory> getCblk() const; 647 virtual status_t onTransact( 648 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); 649 private: 650 sp<PlaybackThread::Track> mTrack; 651 }; 652 653 friend class Client; 654 friend class PlaybackThread::Track; 655 656 657 void removeClient_l(pid_t pid); 658 659 660 // record thread 661 class RecordThread : public ThreadBase, public AudioBufferProvider 662 { 663 public: 664 665 // record track 666 class RecordTrack : public TrackBase { 667 public: 668 RecordTrack(const wp<ThreadBase>& thread, 669 const sp<Client>& client, 670 uint32_t sampleRate, 671 int format, 672 int channelCount, 673 int frameCount, 674 uint32_t flags); 675 ~RecordTrack(); 676 677 virtual status_t start(); 678 virtual void stop(); 679 overflow()680 bool overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; } setOverflow()681 bool setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; } 682 683 void dump(char* buffer, size_t size); 684 private: 685 friend class AudioFlinger; 686 friend class RecordThread; 687 688 RecordTrack(const RecordTrack&); 689 RecordTrack& operator = (const RecordTrack&); 690 691 virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); 692 693 bool mOverflow; 694 }; 695 696 697 RecordThread(const sp<AudioFlinger>& audioFlinger, 698 AudioStreamIn *input, 699 uint32_t sampleRate, 700 uint32_t channels); 701 ~RecordThread(); 702 703 virtual bool threadLoop(); readyToRun()704 virtual status_t readyToRun() { return NO_ERROR; } 705 virtual void onFirstRef(); 706 707 status_t start(RecordTrack* recordTrack); 708 void stop(RecordTrack* recordTrack); 709 status_t dump(int fd, const Vector<String16>& args); getInput()710 AudioStreamIn* getInput() { return mInput; } 711 712 virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); 713 virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); 714 virtual bool checkForNewParameters_l(); 715 virtual String8 getParameters(const String8& keys); 716 virtual void audioConfigChanged(int event, int param = 0); 717 void readInputParameters(); 718 719 private: 720 RecordThread(); 721 AudioStreamIn *mInput; 722 sp<RecordTrack> mActiveTrack; 723 Condition mStartStopCond; 724 AudioResampler *mResampler; 725 int32_t *mRsmpOutBuffer; 726 int16_t *mRsmpInBuffer; 727 size_t mRsmpInIndex; 728 size_t mInputBytes; 729 int mReqChannelCount; 730 uint32_t mReqSampleRate; 731 }; 732 733 class RecordHandle : public android::BnAudioRecord { 734 public: 735 RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack); 736 virtual ~RecordHandle(); 737 virtual status_t start(); 738 virtual void stop(); 739 virtual sp<IMemory> getCblk() const; 740 virtual status_t onTransact( 741 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); 742 private: 743 sp<RecordThread::RecordTrack> mRecordTrack; 744 }; 745 746 friend class RecordThread; 747 friend class PlaybackThread; 748 749 750 mutable Mutex mLock; 751 752 DefaultKeyedVector< pid_t, wp<Client> > mClients; 753 754 mutable Mutex mHardwareLock; 755 AudioHardwareInterface* mAudioHardware; 756 mutable int mHardwareStatus; 757 758 759 DefaultKeyedVector< int, sp<PlaybackThread> > mPlaybackThreads; 760 PlaybackThread::stream_type_t mStreamTypes[AudioSystem::NUM_STREAM_TYPES]; 761 float mMasterVolume; 762 bool mMasterMute; 763 764 DefaultKeyedVector< int, sp<RecordThread> > mRecordThreads; 765 766 SortedVector< sp<IBinder> > mNotificationClients; 767 int mNextThreadId; 768 }; 769 770 // ---------------------------------------------------------------------------- 771 772 }; // namespace android 773 774 #endif // ANDROID_AUDIO_FLINGER_H 775