| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 1 | /* | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 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 | #include <limits.h> | 
|  | 24 |  | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 25 | #include <common_time/cc_helper.h> | 
|  | 26 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 27 | #include <media/IAudioFlinger.h> | 
|  | 28 | #include <media/IAudioFlingerClient.h> | 
|  | 29 | #include <media/IAudioTrack.h> | 
|  | 30 | #include <media/IAudioRecord.h> | 
| Glenn Kasten | 335787f | 2012-01-20 17:00:00 -0800 | [diff] [blame] | 31 | #include <media/AudioSystem.h> | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 32 | #include <media/AudioTrack.h> | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 33 |  | 
|  | 34 | #include <utils/Atomic.h> | 
|  | 35 | #include <utils/Errors.h> | 
|  | 36 | #include <utils/threads.h> | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 37 | #include <utils/SortedVector.h> | 
| Dima Zavin | 799a70e | 2011-04-18 16:57:27 -0700 | [diff] [blame] | 38 | #include <utils/TypeHelpers.h> | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 39 | #include <utils/Vector.h> | 
|  | 40 |  | 
| Mathias Agopian | 5462fc9 | 2010-07-14 18:41:18 -0700 | [diff] [blame] | 41 | #include <binder/BinderService.h> | 
|  | 42 | #include <binder/MemoryDealer.h> | 
|  | 43 |  | 
| Dima Zavin | 6476024 | 2011-05-11 14:15:23 -0700 | [diff] [blame] | 44 | #include <system/audio.h> | 
| Dima Zavin | 7394a4f | 2011-06-13 18:16:26 -0700 | [diff] [blame] | 45 | #include <hardware/audio.h> | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 46 |  | 
|  | 47 | #include "AudioBufferProvider.h" | 
|  | 48 |  | 
| Eric Laurent | feb0db6 | 2011-07-22 09:04:31 -0700 | [diff] [blame] | 49 | #include <powermanager/IPowerManager.h> | 
|  | 50 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 51 | namespace android { | 
|  | 52 |  | 
|  | 53 | class audio_track_cblk_t; | 
|  | 54 | class effect_param_cblk_t; | 
|  | 55 | class AudioMixer; | 
|  | 56 | class AudioBuffer; | 
|  | 57 | class AudioResampler; | 
|  | 58 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 59 | // ---------------------------------------------------------------------------- | 
|  | 60 |  | 
| Glenn Kasten | 53d76db | 2012-03-08 12:32:47 -0800 | [diff] [blame] | 61 | // AudioFlinger has a hard-coded upper limit of 2 channels for capture and playback. | 
|  | 62 | // There is support for > 2 channel tracks down-mixed to 2 channel output via a down-mix effect. | 
|  | 63 | // Adding full support for > 2 channel capture or playback would require more than simply changing | 
|  | 64 | // this #define.  There is an independent hard-coded upper limit in AudioMixer; | 
|  | 65 | // removing that AudioMixer limit would be necessary but insufficient to support > 2 channels. | 
|  | 66 | // The macro FCC_2 highlights some (but not all) places where there is are 2-channel assumptions. | 
|  | 67 | // Search also for "2", "left", "right", "[0]", "[1]", ">> 16", "<< 16", etc. | 
|  | 68 | #define FCC_2 2     // FCC_2 = Fixed Channel Count 2 | 
|  | 69 |  | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 70 | static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 71 |  | 
| Mathias Agopian | 5462fc9 | 2010-07-14 18:41:18 -0700 | [diff] [blame] | 72 | class AudioFlinger : | 
|  | 73 | public BinderService<AudioFlinger>, | 
|  | 74 | public BnAudioFlinger | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 75 | { | 
| Glenn Kasten | 1998661 | 2012-03-09 12:07:30 -0800 | [diff] [blame] | 76 | friend class BinderService<AudioFlinger>;   // for AudioFlinger() | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 77 | public: | 
| Glenn Kasten | 54c3b66 | 2012-01-06 07:46:30 -0800 | [diff] [blame] | 78 | static const char* getServiceName() { return "media.audio_flinger"; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 79 |  | 
|  | 80 | virtual     status_t    dump(int fd, const Vector<String16>& args); | 
|  | 81 |  | 
| Glenn Kasten | 2f732eb | 2012-01-26 09:48:03 -0800 | [diff] [blame] | 82 | // IAudioFlinger interface, in binder opcode order | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 83 | virtual sp<IAudioTrack> createTrack( | 
|  | 84 | pid_t pid, | 
| Glenn Kasten | fff6d71 | 2012-01-12 16:38:12 -0800 | [diff] [blame] | 85 | audio_stream_type_t streamType, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 86 | uint32_t sampleRate, | 
| Glenn Kasten | 58f3021 | 2012-01-12 12:27:51 -0800 | [diff] [blame] | 87 | audio_format_t format, | 
| Jean-Michel Trivi | 0d255b2 | 2011-05-24 15:53:33 -0700 | [diff] [blame] | 88 | uint32_t channelMask, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 89 | int frameCount, | 
| Glenn Kasten | a075db4 | 2012-03-06 11:22:44 -0800 | [diff] [blame] | 90 | IAudioFlinger::track_flags_t flags, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 91 | const sp<IMemory>& sharedBuffer, | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 92 | audio_io_handle_t output, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 93 | int *sessionId, | 
|  | 94 | status_t *status); | 
|  | 95 |  | 
| Glenn Kasten | 2f732eb | 2012-01-26 09:48:03 -0800 | [diff] [blame] | 96 | virtual sp<IAudioRecord> openRecord( | 
|  | 97 | pid_t pid, | 
|  | 98 | audio_io_handle_t input, | 
|  | 99 | uint32_t sampleRate, | 
|  | 100 | audio_format_t format, | 
|  | 101 | uint32_t channelMask, | 
|  | 102 | int frameCount, | 
| Glenn Kasten | a075db4 | 2012-03-06 11:22:44 -0800 | [diff] [blame] | 103 | IAudioFlinger::track_flags_t flags, | 
| Glenn Kasten | 2f732eb | 2012-01-26 09:48:03 -0800 | [diff] [blame] | 104 | int *sessionId, | 
|  | 105 | status_t *status); | 
|  | 106 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 107 | virtual     uint32_t    sampleRate(audio_io_handle_t output) const; | 
|  | 108 | virtual     int         channelCount(audio_io_handle_t output) const; | 
|  | 109 | virtual     audio_format_t format(audio_io_handle_t output) const; | 
|  | 110 | virtual     size_t      frameCount(audio_io_handle_t output) const; | 
|  | 111 | virtual     uint32_t    latency(audio_io_handle_t output) const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 112 |  | 
|  | 113 | virtual     status_t    setMasterVolume(float value); | 
|  | 114 | virtual     status_t    setMasterMute(bool muted); | 
|  | 115 |  | 
|  | 116 | virtual     float       masterVolume() const; | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 117 | virtual     float       masterVolumeSW() const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 118 | virtual     bool        masterMute() const; | 
|  | 119 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 120 | virtual     status_t    setStreamVolume(audio_stream_type_t stream, float value, | 
|  | 121 | audio_io_handle_t output); | 
| Glenn Kasten | fff6d71 | 2012-01-12 16:38:12 -0800 | [diff] [blame] | 122 | virtual     status_t    setStreamMute(audio_stream_type_t stream, bool muted); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 123 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 124 | virtual     float       streamVolume(audio_stream_type_t stream, | 
|  | 125 | audio_io_handle_t output) const; | 
| Glenn Kasten | fff6d71 | 2012-01-12 16:38:12 -0800 | [diff] [blame] | 126 | virtual     bool        streamMute(audio_stream_type_t stream) const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 127 |  | 
| Glenn Kasten | f78aee7 | 2012-01-04 11:00:47 -0800 | [diff] [blame] | 128 | virtual     status_t    setMode(audio_mode_t mode); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 129 |  | 
|  | 130 | virtual     status_t    setMicMute(bool state); | 
|  | 131 | virtual     bool        getMicMute() const; | 
|  | 132 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 133 | virtual     status_t    setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs); | 
|  | 134 | virtual     String8     getParameters(audio_io_handle_t ioHandle, const String8& keys) const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 135 |  | 
|  | 136 | virtual     void        registerClient(const sp<IAudioFlingerClient>& client); | 
|  | 137 |  | 
| Glenn Kasten | f587ba5 | 2012-01-26 16:25:10 -0800 | [diff] [blame] | 138 | virtual     size_t      getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount) const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 139 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 140 | virtual audio_io_handle_t openOutput(uint32_t *pDevices, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 141 | uint32_t *pSamplingRate, | 
| Glenn Kasten | 58f3021 | 2012-01-12 12:27:51 -0800 | [diff] [blame] | 142 | audio_format_t *pFormat, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 143 | uint32_t *pChannels, | 
|  | 144 | uint32_t *pLatencyMs, | 
| Glenn Kasten | 18868c5 | 2012-03-07 09:15:37 -0800 | [diff] [blame] | 145 | audio_policy_output_flags_t flags); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 146 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 147 | virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1, | 
|  | 148 | audio_io_handle_t output2); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 149 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 150 | virtual status_t closeOutput(audio_io_handle_t output); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 151 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 152 | virtual status_t suspendOutput(audio_io_handle_t output); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 153 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 154 | virtual status_t restoreOutput(audio_io_handle_t output); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 155 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 156 | virtual audio_io_handle_t openInput(uint32_t *pDevices, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 157 | uint32_t *pSamplingRate, | 
| Glenn Kasten | 58f3021 | 2012-01-12 12:27:51 -0800 | [diff] [blame] | 158 | audio_format_t *pFormat, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 159 | uint32_t *pChannels, | 
| Glenn Kasten | de9719b | 2012-01-27 12:32:34 -0800 | [diff] [blame] | 160 | audio_in_acoustics_t acoustics); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 161 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 162 | virtual status_t closeInput(audio_io_handle_t input); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 163 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 164 | virtual status_t setStreamOutput(audio_stream_type_t stream, audio_io_handle_t output); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 165 |  | 
|  | 166 | virtual status_t setVoiceVolume(float volume); | 
|  | 167 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 168 | virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, | 
|  | 169 | audio_io_handle_t output) const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 170 |  | 
| Glenn Kasten | 2f732eb | 2012-01-26 09:48:03 -0800 | [diff] [blame] | 171 | virtual     unsigned int  getInputFramesLost(audio_io_handle_t ioHandle) const; | 
|  | 172 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 173 | virtual int newAudioSessionId(); | 
|  | 174 |  | 
| Marco Nelissen | 3a34bef | 2011-08-02 13:33:41 -0700 | [diff] [blame] | 175 | virtual void acquireAudioSessionId(int audioSession); | 
|  | 176 |  | 
|  | 177 | virtual void releaseAudioSessionId(int audioSession); | 
|  | 178 |  | 
| Glenn Kasten | f587ba5 | 2012-01-26 16:25:10 -0800 | [diff] [blame] | 179 | virtual status_t queryNumberEffects(uint32_t *numEffects) const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 180 |  | 
| Glenn Kasten | f587ba5 | 2012-01-26 16:25:10 -0800 | [diff] [blame] | 181 | virtual status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor) const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 182 |  | 
| Glenn Kasten | 5e92a78 | 2012-01-30 07:40:52 -0800 | [diff] [blame] | 183 | virtual status_t getEffectDescriptor(const effect_uuid_t *pUuid, | 
| Glenn Kasten | f587ba5 | 2012-01-26 16:25:10 -0800 | [diff] [blame] | 184 | effect_descriptor_t *descriptor) const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 185 |  | 
|  | 186 | virtual sp<IEffect> createEffect(pid_t pid, | 
|  | 187 | effect_descriptor_t *pDesc, | 
|  | 188 | const sp<IEffectClient>& effectClient, | 
|  | 189 | int32_t priority, | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 190 | audio_io_handle_t io, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 191 | int sessionId, | 
|  | 192 | status_t *status, | 
|  | 193 | int *id, | 
|  | 194 | int *enabled); | 
|  | 195 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 196 | virtual status_t moveEffects(int sessionId, audio_io_handle_t srcOutput, | 
|  | 197 | audio_io_handle_t dstOutput); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 198 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 199 | virtual     status_t    onTransact( | 
|  | 200 | uint32_t code, | 
|  | 201 | const Parcel& data, | 
|  | 202 | Parcel* reply, | 
|  | 203 | uint32_t flags); | 
|  | 204 |  | 
| Glenn Kasten | 2f732eb | 2012-01-26 09:48:03 -0800 | [diff] [blame] | 205 | // end of IAudioFlinger interface | 
|  | 206 |  | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 207 | class SyncEvent; | 
|  | 208 |  | 
|  | 209 | typedef void (*sync_event_callback_t)(const wp<SyncEvent>& event) ; | 
|  | 210 |  | 
|  | 211 | class SyncEvent : public RefBase { | 
|  | 212 | public: | 
|  | 213 | SyncEvent(AudioSystem::sync_event_t type, | 
|  | 214 | int triggerSession, | 
|  | 215 | int listenerSession, | 
|  | 216 | sync_event_callback_t callBack, | 
|  | 217 | void *cookie) | 
|  | 218 | : mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession), | 
|  | 219 | mCallback(callBack), mCookie(cookie) | 
|  | 220 | {} | 
|  | 221 |  | 
|  | 222 | virtual ~SyncEvent() {} | 
|  | 223 |  | 
|  | 224 | void trigger() { Mutex::Autolock _l(mLock); if (mCallback) mCallback(this); } | 
|  | 225 | void cancel() {Mutex::Autolock _l(mLock); mCallback = NULL; } | 
|  | 226 | AudioSystem::sync_event_t type() const { return mType; } | 
|  | 227 | int triggerSession() const { return mTriggerSession; } | 
|  | 228 | int listenerSession() const { return mListenerSession; } | 
|  | 229 | void *cookie() const { return mCookie; } | 
|  | 230 |  | 
|  | 231 | private: | 
|  | 232 | const AudioSystem::sync_event_t mType; | 
|  | 233 | const int mTriggerSession; | 
|  | 234 | const int mListenerSession; | 
|  | 235 | sync_event_callback_t mCallback; | 
|  | 236 | void * const mCookie; | 
|  | 237 | Mutex mLock; | 
|  | 238 | }; | 
|  | 239 |  | 
|  | 240 | sp<SyncEvent> createSyncEvent(AudioSystem::sync_event_t type, | 
|  | 241 | int triggerSession, | 
|  | 242 | int listenerSession, | 
|  | 243 | sync_event_callback_t callBack, | 
|  | 244 | void *cookie); | 
| Glenn Kasten | 2f732eb | 2012-01-26 09:48:03 -0800 | [diff] [blame] | 245 | private: | 
| Glenn Kasten | f78aee7 | 2012-01-04 11:00:47 -0800 | [diff] [blame] | 246 | audio_mode_t getMode() const { return mMode; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 247 |  | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 248 | bool        btNrecIsOff() const { return mBtNrecIsOff; } | 
| Eric Laurent | 59bd0da | 2011-08-01 09:52:20 -0700 | [diff] [blame] | 249 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 250 | AudioFlinger(); | 
|  | 251 | virtual                 ~AudioFlinger(); | 
|  | 252 |  | 
| Glenn Kasten | 2b213bc | 2012-02-02 14:05:20 -0800 | [diff] [blame] | 253 | // call in any IAudioFlinger method that accesses mPrimaryHardwareDev | 
|  | 254 | status_t                initCheck() const { return mPrimaryHardwareDev == NULL ? NO_INIT : NO_ERROR; } | 
|  | 255 |  | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 256 | // RefBase | 
| Dima Zavin | 5a61d2f | 2011-04-19 19:04:32 -0700 | [diff] [blame] | 257 | virtual     void        onFirstRef(); | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 258 |  | 
| Dima Zavin | 799a70e | 2011-04-18 16:57:27 -0700 | [diff] [blame] | 259 | audio_hw_device_t*      findSuitableHwDev_l(uint32_t devices); | 
| Marco Nelissen | 3a34bef | 2011-08-02 13:33:41 -0700 | [diff] [blame] | 260 | void                    purgeStaleEffects_l(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 261 |  | 
| Glenn Kasten | 66fcab9 | 2012-02-24 14:59:21 -0800 | [diff] [blame] | 262 | // standby delay for MIXER and DUPLICATING playback threads is read from property | 
|  | 263 | // ro.audio.flinger_standbytime_ms or defaults to kDefaultStandbyTimeInNsecs | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 264 | static nsecs_t          mStandbyTimeInNsecs; | 
|  | 265 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 266 | // Internal dump utilites. | 
|  | 267 | status_t dumpPermissionDenial(int fd, const Vector<String16>& args); | 
|  | 268 | status_t dumpClients(int fd, const Vector<String16>& args); | 
|  | 269 | status_t dumpInternals(int fd, const Vector<String16>& args); | 
|  | 270 |  | 
|  | 271 | // --- Client --- | 
|  | 272 | class Client : public RefBase { | 
|  | 273 | public: | 
|  | 274 | Client(const sp<AudioFlinger>& audioFlinger, pid_t pid); | 
|  | 275 | virtual             ~Client(); | 
| Glenn Kasten | 435dbe6 | 2012-01-30 10:15:48 -0800 | [diff] [blame] | 276 | sp<MemoryDealer>    heap() const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 277 | pid_t               pid() const { return mPid; } | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 278 | sp<AudioFlinger>    audioFlinger() const { return mAudioFlinger; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 279 |  | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 280 | bool reserveTimedTrack(); | 
|  | 281 | void releaseTimedTrack(); | 
|  | 282 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 283 | private: | 
|  | 284 | Client(const Client&); | 
|  | 285 | Client& operator = (const Client&); | 
| Glenn Kasten | 84afa3b | 2012-01-25 15:28:08 -0800 | [diff] [blame] | 286 | const sp<AudioFlinger> mAudioFlinger; | 
|  | 287 | const sp<MemoryDealer> mMemoryDealer; | 
|  | 288 | const pid_t         mPid; | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 289 |  | 
|  | 290 | Mutex               mTimedTrackLock; | 
|  | 291 | int                 mTimedTrackCount; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 292 | }; | 
|  | 293 |  | 
|  | 294 | // --- Notification Client --- | 
|  | 295 | class NotificationClient : public IBinder::DeathRecipient { | 
|  | 296 | public: | 
|  | 297 | NotificationClient(const sp<AudioFlinger>& audioFlinger, | 
|  | 298 | const sp<IAudioFlingerClient>& client, | 
|  | 299 | pid_t pid); | 
|  | 300 | virtual             ~NotificationClient(); | 
|  | 301 |  | 
| Glenn Kasten | 84afa3b | 2012-01-25 15:28:08 -0800 | [diff] [blame] | 302 | sp<IAudioFlingerClient> audioFlingerClient() const { return mAudioFlingerClient; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 303 |  | 
|  | 304 | // IBinder::DeathRecipient | 
|  | 305 | virtual     void        binderDied(const wp<IBinder>& who); | 
|  | 306 |  | 
|  | 307 | private: | 
|  | 308 | NotificationClient(const NotificationClient&); | 
|  | 309 | NotificationClient& operator = (const NotificationClient&); | 
|  | 310 |  | 
| Glenn Kasten | 84afa3b | 2012-01-25 15:28:08 -0800 | [diff] [blame] | 311 | const sp<AudioFlinger>  mAudioFlinger; | 
|  | 312 | const pid_t             mPid; | 
|  | 313 | const sp<IAudioFlingerClient> mAudioFlingerClient; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 314 | }; | 
|  | 315 |  | 
|  | 316 | class TrackHandle; | 
|  | 317 | class RecordHandle; | 
|  | 318 | class RecordThread; | 
|  | 319 | class PlaybackThread; | 
|  | 320 | class MixerThread; | 
|  | 321 | class DirectOutputThread; | 
|  | 322 | class DuplicatingThread; | 
|  | 323 | class Track; | 
|  | 324 | class RecordTrack; | 
|  | 325 | class EffectModule; | 
|  | 326 | class EffectHandle; | 
|  | 327 | class EffectChain; | 
| Dima Zavin | 799a70e | 2011-04-18 16:57:27 -0700 | [diff] [blame] | 328 | struct AudioStreamOut; | 
|  | 329 | struct AudioStreamIn; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 330 |  | 
|  | 331 | class ThreadBase : public Thread { | 
|  | 332 | public: | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 333 |  | 
| Glenn Kasten | 23bb8be | 2012-01-26 10:38:26 -0800 | [diff] [blame] | 334 | enum type_t { | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 335 | MIXER,              // Thread class is MixerThread | 
|  | 336 | DIRECT,             // Thread class is DirectOutputThread | 
|  | 337 | DUPLICATING,        // Thread class is DuplicatingThread | 
|  | 338 | RECORD              // Thread class is RecordThread | 
|  | 339 | }; | 
|  | 340 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 341 | ThreadBase (const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id, uint32_t device, type_t type); | 
| Glenn Kasten | 23bb8be | 2012-01-26 10:38:26 -0800 | [diff] [blame] | 342 | virtual             ~ThreadBase(); | 
|  | 343 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 344 | status_t dumpBase(int fd, const Vector<String16>& args); | 
| Eric Laurent | 1d2bff0 | 2011-07-24 17:49:51 -0700 | [diff] [blame] | 345 | status_t dumpEffectChains(int fd, const Vector<String16>& args); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 346 |  | 
| Eric Laurent | feb0db6 | 2011-07-22 09:04:31 -0700 | [diff] [blame] | 347 | void clearPowerManager(); | 
|  | 348 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 349 | // base for record and playback | 
|  | 350 | class TrackBase : public AudioBufferProvider, public RefBase { | 
|  | 351 |  | 
|  | 352 | public: | 
|  | 353 | enum track_state { | 
|  | 354 | IDLE, | 
|  | 355 | TERMINATED, | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 356 | // These are order-sensitive; do not change order without reviewing the impact. | 
|  | 357 | // In particular there are assumptions about > STOPPED. | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 358 | STOPPED, | 
|  | 359 | RESUMING, | 
|  | 360 | ACTIVE, | 
|  | 361 | PAUSING, | 
|  | 362 | PAUSED | 
|  | 363 | }; | 
|  | 364 |  | 
| Glenn Kasten | 9eaa557 | 2012-01-20 13:32:16 -0800 | [diff] [blame] | 365 | TrackBase(ThreadBase *thread, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 366 | const sp<Client>& client, | 
|  | 367 | uint32_t sampleRate, | 
| Glenn Kasten | 58f3021 | 2012-01-12 12:27:51 -0800 | [diff] [blame] | 368 | audio_format_t format, | 
| Jean-Michel Trivi | 0d255b2 | 2011-05-24 15:53:33 -0700 | [diff] [blame] | 369 | uint32_t channelMask, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 370 | int frameCount, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 371 | const sp<IMemory>& sharedBuffer, | 
|  | 372 | int sessionId); | 
| Glenn Kasten | c19e224 | 2012-01-30 14:54:39 -0800 | [diff] [blame] | 373 | virtual             ~TrackBase(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 374 |  | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 375 | virtual status_t    start(pid_t tid, | 
|  | 376 | AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, | 
|  | 377 | int triggerSession = 0) = 0; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 378 | virtual void        stop() = 0; | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 379 | sp<IMemory> getCblk() const { return mCblkMemory; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 380 | audio_track_cblk_t* cblk() const { return mCblk; } | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 381 | int         sessionId() const { return mSessionId; } | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 382 | virtual status_t    setSyncEvent(const sp<SyncEvent>& event); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 383 |  | 
|  | 384 | protected: | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 385 | TrackBase(const TrackBase&); | 
|  | 386 | TrackBase& operator = (const TrackBase&); | 
|  | 387 |  | 
| Glenn Kasten | 01c4ebf | 2012-02-22 10:47:35 -0800 | [diff] [blame] | 388 | // AudioBufferProvider interface | 
|  | 389 | virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts) = 0; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 390 | virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); | 
|  | 391 |  | 
| Glenn Kasten | 58f3021 | 2012-01-12 12:27:51 -0800 | [diff] [blame] | 392 | audio_format_t format() const { | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 393 | return mFormat; | 
|  | 394 | } | 
|  | 395 |  | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 396 | int channelCount() const { return mChannelCount; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 397 |  | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 398 | uint32_t channelMask() const { return mChannelMask; } | 
| Jean-Michel Trivi | 0d255b2 | 2011-05-24 15:53:33 -0700 | [diff] [blame] | 399 |  | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 400 | int sampleRate() const; // FIXME inline after cblk sr moved | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 401 |  | 
|  | 402 | void* getBuffer(uint32_t offset, uint32_t frames) const; | 
|  | 403 |  | 
|  | 404 | bool isStopped() const { | 
|  | 405 | return mState == STOPPED; | 
|  | 406 | } | 
|  | 407 |  | 
|  | 408 | bool isTerminated() const { | 
|  | 409 | return mState == TERMINATED; | 
|  | 410 | } | 
|  | 411 |  | 
|  | 412 | bool step(); | 
|  | 413 | void reset(); | 
|  | 414 |  | 
| Glenn Kasten | 84afa3b | 2012-01-25 15:28:08 -0800 | [diff] [blame] | 415 | const wp<ThreadBase> mThread; | 
|  | 416 | /*const*/ sp<Client> mClient;   // see explanation at ~TrackBase() why not const | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 417 | sp<IMemory>         mCblkMemory; | 
|  | 418 | audio_track_cblk_t* mCblk; | 
|  | 419 | void*               mBuffer; | 
|  | 420 | void*               mBufferEnd; | 
|  | 421 | uint32_t            mFrameCount; | 
|  | 422 | // we don't really need a lock for these | 
| Glenn Kasten | b853e98 | 2012-01-26 13:39:18 -0800 | [diff] [blame] | 423 | track_state         mState; | 
| Glenn Kasten | 84afa3b | 2012-01-25 15:28:08 -0800 | [diff] [blame] | 424 | const audio_format_t mFormat; | 
| Glenn Kasten | 5cf034d | 2012-02-21 10:35:56 -0800 | [diff] [blame] | 425 | bool                mStepServerFailed; | 
| Glenn Kasten | 84afa3b | 2012-01-25 15:28:08 -0800 | [diff] [blame] | 426 | const int           mSessionId; | 
| Jean-Michel Trivi | 0d255b2 | 2011-05-24 15:53:33 -0700 | [diff] [blame] | 427 | uint8_t             mChannelCount; | 
|  | 428 | uint32_t            mChannelMask; | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 429 | Vector < sp<SyncEvent> >mSyncEvents; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 430 | }; | 
|  | 431 |  | 
|  | 432 | class ConfigEvent { | 
|  | 433 | public: | 
|  | 434 | ConfigEvent() : mEvent(0), mParam(0) {} | 
|  | 435 |  | 
|  | 436 | int mEvent; | 
|  | 437 | int mParam; | 
|  | 438 | }; | 
|  | 439 |  | 
| Eric Laurent | feb0db6 | 2011-07-22 09:04:31 -0700 | [diff] [blame] | 440 | class PMDeathRecipient : public IBinder::DeathRecipient { | 
|  | 441 | public: | 
|  | 442 | PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {} | 
|  | 443 | virtual     ~PMDeathRecipient() {} | 
|  | 444 |  | 
|  | 445 | // IBinder::DeathRecipient | 
|  | 446 | virtual     void        binderDied(const wp<IBinder>& who); | 
|  | 447 |  | 
|  | 448 | private: | 
|  | 449 | PMDeathRecipient(const PMDeathRecipient&); | 
|  | 450 | PMDeathRecipient& operator = (const PMDeathRecipient&); | 
|  | 451 |  | 
|  | 452 | wp<ThreadBase> mThread; | 
|  | 453 | }; | 
|  | 454 |  | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 455 | virtual     status_t    initCheck() const = 0; | 
| Glenn Kasten | 23bb8be | 2012-01-26 10:38:26 -0800 | [diff] [blame] | 456 | type_t      type() const { return mType; } | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 457 | uint32_t    sampleRate() const { return mSampleRate; } | 
|  | 458 | int         channelCount() const { return mChannelCount; } | 
|  | 459 | audio_format_t format() const { return mFormat; } | 
|  | 460 | size_t      frameCount() const { return mFrameCount; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 461 | void        wakeUp()    { mWaitWorkCV.broadcast(); } | 
| Glenn Kasten | b28686f | 2012-01-06 08:39:38 -0800 | [diff] [blame] | 462 | // Should be "virtual status_t requestExitAndWait()" and override same | 
|  | 463 | // method in Thread, but Thread::requestExitAndWait() is not yet virtual. | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 464 | void        exit(); | 
|  | 465 | virtual     bool        checkForNewParameters_l() = 0; | 
|  | 466 | virtual     status_t    setParameters(const String8& keyValuePairs); | 
|  | 467 | virtual     String8     getParameters(const String8& keys) = 0; | 
|  | 468 | virtual     void        audioConfigChanged_l(int event, int param = 0) = 0; | 
|  | 469 | void        sendConfigEvent(int event, int param = 0); | 
|  | 470 | void        sendConfigEvent_l(int event, int param = 0); | 
|  | 471 | void        processConfigEvents(); | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 472 | audio_io_handle_t id() const { return mId;} | 
| Glenn Kasten | 02fe1bf | 2012-02-24 15:42:17 -0800 | [diff] [blame] | 473 | bool        standby() const { return mStandby; } | 
|  | 474 | uint32_t    device() const { return mDevice; } | 
| Glenn Kasten | 0bf65bd | 2012-02-28 18:32:53 -0800 | [diff] [blame^] | 475 | virtual     audio_stream_t* stream() const = 0; | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 476 |  | 
|  | 477 | sp<EffectHandle> createEffect_l( | 
|  | 478 | const sp<AudioFlinger::Client>& client, | 
|  | 479 | const sp<IEffectClient>& effectClient, | 
|  | 480 | int32_t priority, | 
|  | 481 | int sessionId, | 
|  | 482 | effect_descriptor_t *desc, | 
|  | 483 | int *enabled, | 
|  | 484 | status_t *status); | 
|  | 485 | void disconnectEffect(const sp< EffectModule>& effect, | 
| Marco Nelissen | 3a34bef | 2011-08-02 13:33:41 -0700 | [diff] [blame] | 486 | const wp<EffectHandle>& handle, | 
| Glenn Kasten | 58123c3 | 2012-02-03 10:32:24 -0800 | [diff] [blame] | 487 | bool unpinIfLast); | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 488 |  | 
|  | 489 | // return values for hasAudioSession (bit field) | 
|  | 490 | enum effect_state { | 
|  | 491 | EFFECT_SESSION = 0x1,   // the audio session corresponds to at least one | 
|  | 492 | // effect | 
|  | 493 | TRACK_SESSION = 0x2     // the audio session corresponds to at least one | 
|  | 494 | // track | 
|  | 495 | }; | 
|  | 496 |  | 
|  | 497 | // get effect chain corresponding to session Id. | 
|  | 498 | sp<EffectChain> getEffectChain(int sessionId); | 
|  | 499 | // same as getEffectChain() but must be called with ThreadBase mutex locked | 
|  | 500 | sp<EffectChain> getEffectChain_l(int sessionId); | 
|  | 501 | // add an effect chain to the chain list (mEffectChains) | 
|  | 502 | virtual     status_t addEffectChain_l(const sp<EffectChain>& chain) = 0; | 
|  | 503 | // remove an effect chain from the chain list (mEffectChains) | 
|  | 504 | virtual     size_t removeEffectChain_l(const sp<EffectChain>& chain) = 0; | 
| Glenn Kasten | d805b71 | 2012-02-24 15:42:48 -0800 | [diff] [blame] | 505 | // lock all effect chains Mutexes. Must be called before releasing the | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 506 | // ThreadBase mutex before processing the mixer and effects. This guarantees the | 
|  | 507 | // integrity of the chains during the process. | 
| Glenn Kasten | d805b71 | 2012-02-24 15:42:48 -0800 | [diff] [blame] | 508 | // Also sets the parameter 'effectChains' to current value of mEffectChains. | 
| Glenn Kasten | e53b9ea | 2012-03-12 16:29:55 -0700 | [diff] [blame] | 509 | void lockEffectChains_l(Vector< sp<EffectChain> >& effectChains); | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 510 | // unlock effect chains after process | 
| Glenn Kasten | e53b9ea | 2012-03-12 16:29:55 -0700 | [diff] [blame] | 511 | void unlockEffectChains(const Vector< sp<EffectChain> >& effectChains); | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 512 | // set audio mode to all effect chains | 
| Glenn Kasten | f78aee7 | 2012-01-04 11:00:47 -0800 | [diff] [blame] | 513 | void setMode(audio_mode_t mode); | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 514 | // get effect module with corresponding ID on specified audio session | 
|  | 515 | sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId); | 
|  | 516 | // add and effect module. Also creates the effect chain is none exists for | 
|  | 517 | // the effects audio session | 
|  | 518 | status_t addEffect_l(const sp< EffectModule>& effect); | 
|  | 519 | // remove and effect module. Also removes the effect chain is this was the last | 
|  | 520 | // effect | 
|  | 521 | void removeEffect_l(const sp< EffectModule>& effect); | 
|  | 522 | // detach all tracks connected to an auxiliary effect | 
|  | 523 | virtual     void detachAuxEffect_l(int effectId) {} | 
|  | 524 | // returns either EFFECT_SESSION if effects on this audio session exist in one | 
|  | 525 | // chain, or TRACK_SESSION if tracks on this audio session exist, or both | 
|  | 526 | virtual uint32_t hasAudioSession(int sessionId) = 0; | 
|  | 527 | // the value returned by default implementation is not important as the | 
|  | 528 | // strategy is only meaningful for PlaybackThread which implements this method | 
|  | 529 | virtual uint32_t getStrategyForSession_l(int sessionId) { return 0; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 530 |  | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 531 | // suspend or restore effect according to the type of effect passed. a NULL | 
|  | 532 | // type pointer means suspend all effects in the session | 
|  | 533 | void setEffectSuspended(const effect_uuid_t *type, | 
|  | 534 | bool suspend, | 
|  | 535 | int sessionId = AUDIO_SESSION_OUTPUT_MIX); | 
|  | 536 | // check if some effects must be suspended/restored when an effect is enabled | 
|  | 537 | // or disabled | 
| Eric Laurent | a85a74a | 2011-10-19 11:44:54 -0700 | [diff] [blame] | 538 | void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect, | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 539 | bool enabled, | 
|  | 540 | int sessionId = AUDIO_SESSION_OUTPUT_MIX); | 
| Eric Laurent | a85a74a | 2011-10-19 11:44:54 -0700 | [diff] [blame] | 541 | void checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect, | 
|  | 542 | bool enabled, | 
|  | 543 | int sessionId = AUDIO_SESSION_OUTPUT_MIX); | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 544 |  | 
|  | 545 | virtual status_t    setSyncEvent(const sp<SyncEvent>& event) = 0; | 
|  | 546 | virtual bool        isValidSyncEvent(const sp<SyncEvent>& event) = 0; | 
|  | 547 |  | 
|  | 548 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 549 | mutable     Mutex                   mLock; | 
|  | 550 |  | 
|  | 551 | protected: | 
|  | 552 |  | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 553 | // entry describing an effect being suspended in mSuspendedSessions keyed vector | 
|  | 554 | class SuspendedSessionDesc : public RefBase { | 
|  | 555 | public: | 
|  | 556 | SuspendedSessionDesc() : mRefCount(0) {} | 
|  | 557 |  | 
|  | 558 | int mRefCount;          // number of active suspend requests | 
|  | 559 | effect_uuid_t mType;    // effect type UUID | 
|  | 560 | }; | 
|  | 561 |  | 
| Eric Laurent | feb0db6 | 2011-07-22 09:04:31 -0700 | [diff] [blame] | 562 | void        acquireWakeLock(); | 
|  | 563 | void        acquireWakeLock_l(); | 
|  | 564 | void        releaseWakeLock(); | 
|  | 565 | void        releaseWakeLock_l(); | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 566 | void setEffectSuspended_l(const effect_uuid_t *type, | 
|  | 567 | bool suspend, | 
|  | 568 | int sessionId = AUDIO_SESSION_OUTPUT_MIX); | 
|  | 569 | // updated mSuspendedSessions when an effect suspended or restored | 
|  | 570 | void        updateSuspendedSessions_l(const effect_uuid_t *type, | 
|  | 571 | bool suspend, | 
|  | 572 | int sessionId); | 
|  | 573 | // check if some effects must be suspended when an effect chain is added | 
|  | 574 | void checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain); | 
| Eric Laurent | feb0db6 | 2011-07-22 09:04:31 -0700 | [diff] [blame] | 575 |  | 
| Glenn Kasten | 1998661 | 2012-03-09 12:07:30 -0800 | [diff] [blame] | 576 | friend class AudioFlinger;      // for mEffectChains | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 577 |  | 
| Glenn Kasten | 23bb8be | 2012-01-26 10:38:26 -0800 | [diff] [blame] | 578 | const type_t            mType; | 
| Glenn Kasten | cbc52bf | 2012-03-01 09:21:37 -0800 | [diff] [blame] | 579 |  | 
|  | 580 | // Used by parameters, config events, addTrack_l, exit | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 581 | Condition               mWaitWorkCV; | 
| Glenn Kasten | cbc52bf | 2012-03-01 09:21:37 -0800 | [diff] [blame] | 582 |  | 
| Glenn Kasten | 84afa3b | 2012-01-25 15:28:08 -0800 | [diff] [blame] | 583 | const sp<AudioFlinger>  mAudioFlinger; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 584 | uint32_t                mSampleRate; | 
|  | 585 | size_t                  mFrameCount; | 
| Jean-Michel Trivi | 0d255b2 | 2011-05-24 15:53:33 -0700 | [diff] [blame] | 586 | uint32_t                mChannelMask; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 587 | uint16_t                mChannelCount; | 
| Glenn Kasten | b998065 | 2012-01-11 09:48:27 -0800 | [diff] [blame] | 588 | size_t                  mFrameSize; | 
| Glenn Kasten | 58f3021 | 2012-01-12 12:27:51 -0800 | [diff] [blame] | 589 | audio_format_t          mFormat; | 
| Glenn Kasten | cbc52bf | 2012-03-01 09:21:37 -0800 | [diff] [blame] | 590 |  | 
|  | 591 | // Parameter sequence by client: binder thread calling setParameters(): | 
|  | 592 | //  1. Lock mLock | 
|  | 593 | //  2. Append to mNewParameters | 
|  | 594 | //  3. mWaitWorkCV.signal | 
|  | 595 | //  4. mParamCond.waitRelative with timeout | 
|  | 596 | //  5. read mParamStatus | 
|  | 597 | //  6. mWaitWorkCV.signal | 
|  | 598 | //  7. Unlock | 
|  | 599 | // | 
|  | 600 | // Parameter sequence by server: threadLoop calling checkForNewParameters_l(): | 
|  | 601 | // 1. Lock mLock | 
|  | 602 | // 2. If there is an entry in mNewParameters proceed ... | 
|  | 603 | // 2. Read first entry in mNewParameters | 
|  | 604 | // 3. Process | 
|  | 605 | // 4. Remove first entry from mNewParameters | 
|  | 606 | // 5. Set mParamStatus | 
|  | 607 | // 6. mParamCond.signal | 
|  | 608 | // 7. mWaitWorkCV.wait with timeout (this is to avoid overwriting mParamStatus) | 
|  | 609 | // 8. Unlock | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 610 | Condition               mParamCond; | 
|  | 611 | Vector<String8>         mNewParameters; | 
|  | 612 | status_t                mParamStatus; | 
| Glenn Kasten | cbc52bf | 2012-03-01 09:21:37 -0800 | [diff] [blame] | 613 |  | 
| Glenn Kasten | f3990f2 | 2011-12-13 11:50:00 -0800 | [diff] [blame] | 614 | Vector<ConfigEvent>     mConfigEvents; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 615 | bool                    mStandby; | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 616 | const audio_io_handle_t mId; | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 617 | Vector< sp<EffectChain> > mEffectChains; | 
|  | 618 | uint32_t                mDevice;    // output device for PlaybackThread | 
|  | 619 | // input + output devices for RecordThread | 
| Glenn Kasten | 480b468 | 2012-02-28 12:30:08 -0800 | [diff] [blame] | 620 | static const int        kNameLength = 16;   // prctl(PR_SET_NAME) limit | 
| Eric Laurent | feb0db6 | 2011-07-22 09:04:31 -0700 | [diff] [blame] | 621 | char                    mName[kNameLength]; | 
|  | 622 | sp<IPowerManager>       mPowerManager; | 
|  | 623 | sp<IBinder>             mWakeLockToken; | 
| Glenn Kasten | 84afa3b | 2012-01-25 15:28:08 -0800 | [diff] [blame] | 624 | const sp<PMDeathRecipient> mDeathRecipient; | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 625 | // list of suspended effects per session and per type. The first vector is | 
|  | 626 | // keyed by session ID, the second by type UUID timeLow field | 
|  | 627 | KeyedVector< int, KeyedVector< int, sp<SuspendedSessionDesc> > >  mSuspendedSessions; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 628 | }; | 
|  | 629 |  | 
| Glenn Kasten | b7bf796 | 2012-02-08 12:36:25 -0800 | [diff] [blame] | 630 | struct  stream_type_t { | 
|  | 631 | stream_type_t() | 
|  | 632 | :   volume(1.0f), | 
|  | 633 | mute(false), | 
|  | 634 | valid(true) | 
|  | 635 | { | 
|  | 636 | } | 
|  | 637 | float       volume; | 
|  | 638 | bool        mute; | 
|  | 639 | bool        valid; | 
|  | 640 | }; | 
|  | 641 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 642 | // --- PlaybackThread --- | 
|  | 643 | class PlaybackThread : public ThreadBase { | 
|  | 644 | public: | 
|  | 645 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 646 | enum mixer_state { | 
| Glenn Kasten | d805b71 | 2012-02-24 15:42:48 -0800 | [diff] [blame] | 647 | MIXER_IDLE,             // no active tracks | 
|  | 648 | MIXER_TRACKS_ENABLED,   // at least one active track, but no track has any data ready | 
|  | 649 | MIXER_TRACKS_READY      // at least one active track, and at least one track has data | 
|  | 650 | // standby mode does not have an enum value | 
|  | 651 | // suspend by audio policy manager is orthogonal to mixer state | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 652 | }; | 
|  | 653 |  | 
|  | 654 | // playback track | 
|  | 655 | class Track : public TrackBase { | 
|  | 656 | public: | 
| Glenn Kasten | 9eaa557 | 2012-01-20 13:32:16 -0800 | [diff] [blame] | 657 | Track(  PlaybackThread *thread, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 658 | const sp<Client>& client, | 
| Glenn Kasten | fff6d71 | 2012-01-12 16:38:12 -0800 | [diff] [blame] | 659 | audio_stream_type_t streamType, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 660 | uint32_t sampleRate, | 
| Glenn Kasten | 58f3021 | 2012-01-12 12:27:51 -0800 | [diff] [blame] | 661 | audio_format_t format, | 
| Jean-Michel Trivi | 0d255b2 | 2011-05-24 15:53:33 -0700 | [diff] [blame] | 662 | uint32_t channelMask, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 663 | int frameCount, | 
|  | 664 | const sp<IMemory>& sharedBuffer, | 
|  | 665 | int sessionId); | 
| Glenn Kasten | c19e224 | 2012-01-30 14:54:39 -0800 | [diff] [blame] | 666 | virtual             ~Track(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 667 |  | 
|  | 668 | void        dump(char* buffer, size_t size); | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 669 | virtual status_t    start(pid_t tid, | 
|  | 670 | AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, | 
|  | 671 | int triggerSession = 0); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 672 | virtual void        stop(); | 
|  | 673 | void        pause(); | 
|  | 674 |  | 
|  | 675 | void        flush(); | 
|  | 676 | void        destroy(); | 
|  | 677 | void        mute(bool); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 678 | int name() const { | 
|  | 679 | return mName; | 
|  | 680 | } | 
|  | 681 |  | 
| Glenn Kasten | 02bbd20 | 2012-02-08 12:35:35 -0800 | [diff] [blame] | 682 | audio_stream_type_t streamType() const { | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 683 | return mStreamType; | 
|  | 684 | } | 
|  | 685 | status_t    attachAuxEffect(int EffectId); | 
|  | 686 | void        setAuxBuffer(int EffectId, int32_t *buffer); | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 687 | int32_t     *auxBuffer() const { return mAuxBuffer; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 688 | void        setMainBuffer(int16_t *buffer) { mMainBuffer = buffer; } | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 689 | int16_t     *mainBuffer() const { return mMainBuffer; } | 
|  | 690 | int         auxEffectId() const { return mAuxEffectId; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 691 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 692 | protected: | 
| Glenn Kasten | 1998661 | 2012-03-09 12:07:30 -0800 | [diff] [blame] | 693 | // for numerous | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 694 | friend class PlaybackThread; | 
|  | 695 | friend class MixerThread; | 
|  | 696 | friend class DirectOutputThread; | 
|  | 697 |  | 
|  | 698 | Track(const Track&); | 
|  | 699 | Track& operator = (const Track&); | 
|  | 700 |  | 
| Glenn Kasten | 01c4ebf | 2012-02-22 10:47:35 -0800 | [diff] [blame] | 701 | // AudioBufferProvider interface | 
|  | 702 | virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts = kInvalidPTS); | 
|  | 703 | // releaseBuffer() not overridden | 
|  | 704 |  | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 705 | virtual uint32_t framesReady() const; | 
|  | 706 |  | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 707 | bool isMuted() const { return mMute; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 708 | bool isPausing() const { | 
|  | 709 | return mState == PAUSING; | 
|  | 710 | } | 
|  | 711 | bool isPaused() const { | 
|  | 712 | return mState == PAUSED; | 
|  | 713 | } | 
|  | 714 | bool isReady() const; | 
|  | 715 | void setPaused() { mState = PAUSED; } | 
|  | 716 | void reset(); | 
|  | 717 |  | 
|  | 718 | bool isOutputTrack() const { | 
| Dima Zavin | fce7a47 | 2011-04-19 22:30:36 -0700 | [diff] [blame] | 719 | return (mStreamType == AUDIO_STREAM_CNT); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 720 | } | 
|  | 721 |  | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 722 | bool presentationComplete(size_t framesWritten, size_t audioHalFrames); | 
|  | 723 | void triggerEvents(AudioSystem::sync_event_t type); | 
|  | 724 |  | 
| Glenn Kasten | 1998661 | 2012-03-09 12:07:30 -0800 | [diff] [blame] | 725 | public: | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 726 | virtual bool isTimedTrack() const { return false; } | 
| Glenn Kasten | 1998661 | 2012-03-09 12:07:30 -0800 | [diff] [blame] | 727 | protected: | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 728 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 729 | // we don't really need a lock for these | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 730 | volatile bool       mMute; | 
|  | 731 | // FILLED state is used for suppressing volume ramp at begin of playing | 
|  | 732 | enum {FS_FILLING, FS_FILLED, FS_ACTIVE}; | 
|  | 733 | mutable uint8_t     mFillingUpStatus; | 
|  | 734 | int8_t              mRetryCount; | 
| Glenn Kasten | f995901 | 2012-03-19 11:14:37 -0700 | [diff] [blame] | 735 | const sp<IMemory>   mSharedBuffer; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 736 | bool                mResetDone; | 
| Glenn Kasten | f995901 | 2012-03-19 11:14:37 -0700 | [diff] [blame] | 737 | const audio_stream_type_t mStreamType; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 738 | int                 mName; | 
|  | 739 | int16_t             *mMainBuffer; | 
|  | 740 | int32_t             *mAuxBuffer; | 
|  | 741 | int                 mAuxEffectId; | 
| Eric Laurent | 8f45bd7 | 2010-08-31 13:50:07 -0700 | [diff] [blame] | 742 | bool                mHasVolumeController; | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 743 | size_t              mPresentationCompleteFrames; // number of frames written to the audio HAL | 
|  | 744 | // when this track will be fully rendered | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 745 | };  // end of Track | 
|  | 746 |  | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 747 | class TimedTrack : public Track { | 
|  | 748 | public: | 
| Glenn Kasten | 9eaa557 | 2012-01-20 13:32:16 -0800 | [diff] [blame] | 749 | static sp<TimedTrack> create(PlaybackThread *thread, | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 750 | const sp<Client>& client, | 
|  | 751 | audio_stream_type_t streamType, | 
|  | 752 | uint32_t sampleRate, | 
|  | 753 | audio_format_t format, | 
|  | 754 | uint32_t channelMask, | 
|  | 755 | int frameCount, | 
|  | 756 | const sp<IMemory>& sharedBuffer, | 
|  | 757 | int sessionId); | 
|  | 758 | ~TimedTrack(); | 
|  | 759 |  | 
|  | 760 | class TimedBuffer { | 
|  | 761 | public: | 
|  | 762 | TimedBuffer(); | 
|  | 763 | TimedBuffer(const sp<IMemory>& buffer, int64_t pts); | 
|  | 764 | const sp<IMemory>& buffer() const { return mBuffer; } | 
|  | 765 | int64_t pts() const { return mPTS; } | 
|  | 766 | int position() const { return mPosition; } | 
|  | 767 | void setPosition(int pos) { mPosition = pos; } | 
|  | 768 | private: | 
|  | 769 | sp<IMemory> mBuffer; | 
|  | 770 | int64_t mPTS; | 
|  | 771 | int mPosition; | 
|  | 772 | }; | 
|  | 773 |  | 
|  | 774 | virtual bool isTimedTrack() const { return true; } | 
|  | 775 |  | 
|  | 776 | virtual uint32_t framesReady() const; | 
|  | 777 |  | 
| Glenn Kasten | 01c4ebf | 2012-02-22 10:47:35 -0800 | [diff] [blame] | 778 | // AudioBufferProvider interface | 
|  | 779 | virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts); | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 780 | virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); | 
| Glenn Kasten | 01c4ebf | 2012-02-22 10:47:35 -0800 | [diff] [blame] | 781 |  | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 782 | void timedYieldSamples(AudioBufferProvider::Buffer* buffer); | 
|  | 783 | void timedYieldSilence(uint32_t numFrames, | 
|  | 784 | AudioBufferProvider::Buffer* buffer); | 
|  | 785 |  | 
|  | 786 | status_t    allocateTimedBuffer(size_t size, | 
|  | 787 | sp<IMemory>* buffer); | 
|  | 788 | status_t    queueTimedBuffer(const sp<IMemory>& buffer, | 
|  | 789 | int64_t pts); | 
|  | 790 | status_t    setMediaTimeTransform(const LinearTransform& xform, | 
|  | 791 | TimedAudioTrack::TargetTimeline target); | 
|  | 792 | void        trimTimedBufferQueue_l(); | 
|  | 793 |  | 
|  | 794 | private: | 
| Glenn Kasten | 9eaa557 | 2012-01-20 13:32:16 -0800 | [diff] [blame] | 795 | TimedTrack(PlaybackThread *thread, | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 796 | const sp<Client>& client, | 
|  | 797 | audio_stream_type_t streamType, | 
|  | 798 | uint32_t sampleRate, | 
|  | 799 | audio_format_t format, | 
|  | 800 | uint32_t channelMask, | 
|  | 801 | int frameCount, | 
|  | 802 | const sp<IMemory>& sharedBuffer, | 
|  | 803 | int sessionId); | 
|  | 804 |  | 
|  | 805 | uint64_t            mLocalTimeFreq; | 
|  | 806 | LinearTransform     mLocalTimeToSampleTransform; | 
|  | 807 | sp<MemoryDealer>    mTimedMemoryDealer; | 
|  | 808 | Vector<TimedBuffer> mTimedBufferQueue; | 
|  | 809 | uint8_t*            mTimedSilenceBuffer; | 
|  | 810 | uint32_t            mTimedSilenceBufferSize; | 
|  | 811 | mutable Mutex       mTimedBufferQueueLock; | 
|  | 812 | bool                mTimedAudioOutputOnTime; | 
|  | 813 | CCHelper            mCCHelper; | 
|  | 814 |  | 
|  | 815 | Mutex               mMediaTimeTransformLock; | 
|  | 816 | LinearTransform     mMediaTimeTransform; | 
|  | 817 | bool                mMediaTimeTransformValid; | 
|  | 818 | TimedAudioTrack::TargetTimeline mMediaTimeTransformTarget; | 
|  | 819 | }; | 
|  | 820 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 821 |  | 
|  | 822 | // playback track | 
|  | 823 | class OutputTrack : public Track { | 
|  | 824 | public: | 
|  | 825 |  | 
|  | 826 | class Buffer: public AudioBufferProvider::Buffer { | 
|  | 827 | public: | 
|  | 828 | int16_t *mBuffer; | 
|  | 829 | }; | 
|  | 830 |  | 
| Glenn Kasten | 9eaa557 | 2012-01-20 13:32:16 -0800 | [diff] [blame] | 831 | OutputTrack(PlaybackThread *thread, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 832 | DuplicatingThread *sourceThread, | 
|  | 833 | uint32_t sampleRate, | 
| Glenn Kasten | 58f3021 | 2012-01-12 12:27:51 -0800 | [diff] [blame] | 834 | audio_format_t format, | 
| Jean-Michel Trivi | 0d255b2 | 2011-05-24 15:53:33 -0700 | [diff] [blame] | 835 | uint32_t channelMask, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 836 | int frameCount); | 
| Glenn Kasten | c19e224 | 2012-01-30 14:54:39 -0800 | [diff] [blame] | 837 | virtual             ~OutputTrack(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 838 |  | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 839 | virtual status_t    start(pid_t tid, | 
|  | 840 | AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, | 
|  | 841 | int triggerSession = 0); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 842 | virtual void        stop(); | 
|  | 843 | bool        write(int16_t* data, uint32_t frames); | 
| Glenn Kasten | a111792 | 2012-01-26 10:53:32 -0800 | [diff] [blame] | 844 | bool        bufferQueueEmpty() const { return mBufferQueue.size() == 0; } | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 845 | bool        isActive() const { return mActive; } | 
|  | 846 | const wp<ThreadBase>& thread() const { return mThread; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 847 |  | 
|  | 848 | private: | 
|  | 849 |  | 
| Glenn Kasten | 335787f | 2012-01-20 17:00:00 -0800 | [diff] [blame] | 850 | enum { | 
|  | 851 | NO_MORE_BUFFERS = 0x80000001,   // same in AudioTrack.h, ok to be different value | 
|  | 852 | }; | 
|  | 853 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 854 | status_t            obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs); | 
|  | 855 | void                clearBufferQueue(); | 
|  | 856 |  | 
|  | 857 | // Maximum number of pending buffers allocated by OutputTrack::write() | 
|  | 858 | static const uint8_t kMaxOverFlowBuffers = 10; | 
|  | 859 |  | 
|  | 860 | Vector < Buffer* >          mBufferQueue; | 
|  | 861 | AudioBufferProvider::Buffer mOutBuffer; | 
|  | 862 | bool                        mActive; | 
| Glenn Kasten | 84afa3b | 2012-01-25 15:28:08 -0800 | [diff] [blame] | 863 | DuplicatingThread* const mSourceThread; // for waitTimeMs() in write() | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 864 | };  // end of OutputTrack | 
|  | 865 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 866 | PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, | 
|  | 867 | audio_io_handle_t id, uint32_t device, type_t type); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 868 | virtual             ~PlaybackThread(); | 
|  | 869 |  | 
| Glenn Kasten | 688aac7 | 2012-03-09 10:30:26 -0800 | [diff] [blame] | 870 | status_t    dump(int fd, const Vector<String16>& args); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 871 |  | 
|  | 872 | // Thread virtuals | 
|  | 873 | virtual     status_t    readyToRun(); | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 874 | virtual     bool        threadLoop(); | 
|  | 875 |  | 
|  | 876 | // RefBase | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 877 | virtual     void        onFirstRef(); | 
|  | 878 |  | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 879 | protected: | 
|  | 880 | // Code snippets that were lifted up out of threadLoop() | 
|  | 881 | virtual     void        threadLoop_mix() = 0; | 
|  | 882 | virtual     void        threadLoop_sleepTime() = 0; | 
|  | 883 | virtual     void        threadLoop_write(); | 
|  | 884 | virtual     void        threadLoop_standby(); | 
|  | 885 |  | 
| Glenn Kasten | 1465f0c | 2012-03-06 11:23:32 -0800 | [diff] [blame] | 886 | // prepareTracks_l reads and writes mActiveTracks, and also returns the | 
|  | 887 | // pending set of tracks to remove via Vector 'tracksToRemove'.  The caller is | 
|  | 888 | // responsible for clearing or destroying this Vector later on, when it | 
|  | 889 | // is safe to do so. That will drop the final ref count and destroy the tracks. | 
|  | 890 | virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove) = 0; | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 891 |  | 
|  | 892 | public: | 
|  | 893 |  | 
| Glenn Kasten | e0feee3 | 2011-12-13 11:53:26 -0800 | [diff] [blame] | 894 | virtual     status_t    initCheck() const { return (mOutput == NULL) ? NO_INIT : NO_ERROR; } | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 895 |  | 
| Glenn Kasten | 688aac7 | 2012-03-09 10:30:26 -0800 | [diff] [blame] | 896 | // return estimated latency in milliseconds, as reported by HAL | 
|  | 897 | uint32_t    latency() const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 898 |  | 
| Glenn Kasten | 6637baa | 2012-01-09 09:40:36 -0800 | [diff] [blame] | 899 | void        setMasterVolume(float value); | 
|  | 900 | void        setMasterMute(bool muted); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 901 |  | 
| Glenn Kasten | 6637baa | 2012-01-09 09:40:36 -0800 | [diff] [blame] | 902 | void        setStreamVolume(audio_stream_type_t stream, float value); | 
|  | 903 | void        setStreamMute(audio_stream_type_t stream, bool muted); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 904 |  | 
| Glenn Kasten | 6637baa | 2012-01-09 09:40:36 -0800 | [diff] [blame] | 905 | float       streamVolume(audio_stream_type_t stream) const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 906 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 907 | sp<Track>   createTrack_l( | 
|  | 908 | const sp<AudioFlinger::Client>& client, | 
| Glenn Kasten | fff6d71 | 2012-01-12 16:38:12 -0800 | [diff] [blame] | 909 | audio_stream_type_t streamType, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 910 | uint32_t sampleRate, | 
| Glenn Kasten | 58f3021 | 2012-01-12 12:27:51 -0800 | [diff] [blame] | 911 | audio_format_t format, | 
| Jean-Michel Trivi | 0d255b2 | 2011-05-24 15:53:33 -0700 | [diff] [blame] | 912 | uint32_t channelMask, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 913 | int frameCount, | 
|  | 914 | const sp<IMemory>& sharedBuffer, | 
|  | 915 | int sessionId, | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 916 | bool isTimed, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 917 | status_t *status); | 
|  | 918 |  | 
| Glenn Kasten | aed850d | 2012-01-26 09:46:34 -0800 | [diff] [blame] | 919 | AudioStreamOut* getOutput() const; | 
| Eric Laurent | b8ba0a9 | 2011-08-07 16:32:26 -0700 | [diff] [blame] | 920 | AudioStreamOut* clearOutput(); | 
| Glenn Kasten | 0bf65bd | 2012-02-28 18:32:53 -0800 | [diff] [blame^] | 921 | virtual audio_stream_t* stream() const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 922 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 923 | void        suspend() { mSuspended++; } | 
| Glenn Kasten | c455fe9 | 2012-02-29 07:07:30 -0800 | [diff] [blame] | 924 | void        restore() { if (mSuspended > 0) mSuspended--; } | 
|  | 925 | bool        isSuspended() const { return (mSuspended > 0); } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 926 | virtual     String8     getParameters(const String8& keys); | 
|  | 927 | virtual     void        audioConfigChanged_l(int event, int param = 0); | 
| Glenn Kasten | 688aac7 | 2012-03-09 10:30:26 -0800 | [diff] [blame] | 928 | status_t    getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames); | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 929 | int16_t     *mixBuffer() const { return mMixBuffer; }; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 930 |  | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 931 | virtual     void detachAuxEffect_l(int effectId); | 
| Eric Laurent | de07013 | 2010-07-13 04:45:46 -0700 | [diff] [blame] | 932 | status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track> track, | 
|  | 933 | int EffectId); | 
|  | 934 | status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track> track, | 
|  | 935 | int EffectId); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 936 |  | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 937 | virtual status_t addEffectChain_l(const sp<EffectChain>& chain); | 
|  | 938 | virtual size_t removeEffectChain_l(const sp<EffectChain>& chain); | 
|  | 939 | virtual uint32_t hasAudioSession(int sessionId); | 
|  | 940 | virtual uint32_t getStrategyForSession_l(int sessionId); | 
| Eric Laurent | de07013 | 2010-07-13 04:45:46 -0700 | [diff] [blame] | 941 |  | 
| Glenn Kasten | fff6d71 | 2012-01-12 16:38:12 -0800 | [diff] [blame] | 942 | void setStreamValid(audio_stream_type_t streamType, bool valid); | 
| Eric Laurent | 9f6530f | 2011-08-30 10:18:54 -0700 | [diff] [blame] | 943 |  | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 944 | virtual status_t setSyncEvent(const sp<SyncEvent>& event); | 
|  | 945 | virtual bool     isValidSyncEvent(const sp<SyncEvent>& event); | 
|  | 946 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 947 | protected: | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 948 | int16_t*                        mMixBuffer; | 
| Glenn Kasten | c455fe9 | 2012-02-29 07:07:30 -0800 | [diff] [blame] | 949 | uint32_t                        mSuspended;     // suspend count, > 0 means suspended | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 950 | int                             mBytesWritten; | 
| Glenn Kasten | 9806710 | 2011-12-13 11:47:54 -0800 | [diff] [blame] | 951 | private: | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 952 | // mMasterMute is in both PlaybackThread and in AudioFlinger.  When a | 
|  | 953 | // PlaybackThread needs to find out if master-muted, it checks it's local | 
|  | 954 | // copy rather than the one in AudioFlinger.  This optimization saves a lock. | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 955 | bool                            mMasterMute; | 
| Glenn Kasten | 6637baa | 2012-01-09 09:40:36 -0800 | [diff] [blame] | 956 | void        setMasterMute_l(bool muted) { mMasterMute = muted; } | 
| Glenn Kasten | 9806710 | 2011-12-13 11:47:54 -0800 | [diff] [blame] | 957 | protected: | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 958 | SortedVector< wp<Track> >       mActiveTracks; | 
|  | 959 |  | 
| Glenn Kasten | 17a736c | 2012-02-14 08:52:15 -0800 | [diff] [blame] | 960 | // Allocate a track name.  Returns name >= 0 if successful, -1 on failure. | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 961 | virtual int             getTrackName_l() = 0; | 
|  | 962 | virtual void            deleteTrackName_l(int name) = 0; | 
| Glenn Kasten | 0bf65bd | 2012-02-28 18:32:53 -0800 | [diff] [blame^] | 963 |  | 
|  | 964 | // Time to sleep between cycles when: | 
|  | 965 | virtual uint32_t        activeSleepTimeUs() const;      // mixer state MIXER_TRACKS_ENABLED | 
|  | 966 | virtual uint32_t        idleSleepTimeUs() const = 0;    // mixer state MIXER_IDLE | 
|  | 967 | virtual uint32_t        suspendSleepTimeUs() const = 0; // audio policy manager suspended us | 
|  | 968 | // No sleep when mixer state == MIXER_TRACKS_READY; relies on audio HAL stream->write() | 
|  | 969 | // No sleep in standby mode; waits on a condition | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 970 |  | 
| Glenn Kasten | 37d825e | 2012-02-24 07:21:48 -0800 | [diff] [blame] | 971 | // Code snippets that are temporarily lifted up out of threadLoop() until the merge | 
|  | 972 | void        checkSilentMode_l(); | 
|  | 973 |  | 
| Glenn Kasten | fa26a85 | 2012-03-06 11:28:04 -0800 | [diff] [blame] | 974 | // Non-trivial for DUPLICATING only | 
|  | 975 | virtual     void        saveOutputTracks() { } | 
|  | 976 | virtual     void        clearOutputTracks() { } | 
|  | 977 |  | 
| Glenn Kasten | 66fcab9 | 2012-02-24 14:59:21 -0800 | [diff] [blame] | 978 | // Cache various calculated values, at threadLoop() entry and after a parameter change | 
|  | 979 | virtual     void        cacheParameters_l(); | 
|  | 980 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 981 | private: | 
|  | 982 |  | 
| Glenn Kasten | 1998661 | 2012-03-09 12:07:30 -0800 | [diff] [blame] | 983 | friend class AudioFlinger;      // for numerous | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 984 |  | 
|  | 985 | PlaybackThread(const Client&); | 
|  | 986 | PlaybackThread& operator = (const PlaybackThread&); | 
|  | 987 |  | 
|  | 988 | status_t    addTrack_l(const sp<Track>& track); | 
|  | 989 | void        destroyTrack_l(const sp<Track>& track); | 
| Eric Laurent | b469b94 | 2011-05-09 12:09:06 -0700 | [diff] [blame] | 990 | void        removeTrack_l(const sp<Track>& track); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 991 |  | 
|  | 992 | void        readOutputParameters(); | 
|  | 993 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 994 | virtual status_t    dumpInternals(int fd, const Vector<String16>& args); | 
|  | 995 | status_t    dumpTracks(int fd, const Vector<String16>& args); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 996 |  | 
|  | 997 | SortedVector< sp<Track> >       mTracks; | 
| Glenn Kasten | 263709e | 2012-01-06 08:40:01 -0800 | [diff] [blame] | 998 | // mStreamTypes[] uses 1 additional stream type internally for the OutputTrack used by DuplicatingThread | 
| Dima Zavin | fce7a47 | 2011-04-19 22:30:36 -0700 | [diff] [blame] | 999 | stream_type_t                   mStreamTypes[AUDIO_STREAM_CNT + 1]; | 
| Glenn Kasten | aed850d | 2012-01-26 09:46:34 -0800 | [diff] [blame] | 1000 | AudioStreamOut                  *mOutput; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1001 | float                           mMasterVolume; | 
|  | 1002 | nsecs_t                         mLastWriteTime; | 
|  | 1003 | int                             mNumWrites; | 
|  | 1004 | int                             mNumDelayedWrites; | 
|  | 1005 | bool                            mInWrite; | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1006 |  | 
|  | 1007 | // FIXME rename these former local variables of threadLoop to standard "m" names | 
|  | 1008 | nsecs_t                         standbyTime; | 
|  | 1009 | size_t                          mixBufferSize; | 
| Glenn Kasten | 66fcab9 | 2012-02-24 14:59:21 -0800 | [diff] [blame] | 1010 |  | 
|  | 1011 | // cached copies of activeSleepTimeUs() and idleSleepTimeUs() made by cacheParameters_l() | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1012 | uint32_t                        activeSleepTime; | 
|  | 1013 | uint32_t                        idleSleepTime; | 
| Glenn Kasten | 66fcab9 | 2012-02-24 14:59:21 -0800 | [diff] [blame] | 1014 |  | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1015 | uint32_t                        sleepTime; | 
| Glenn Kasten | fec279f | 2012-03-08 07:47:15 -0800 | [diff] [blame] | 1016 |  | 
|  | 1017 | // mixer status returned by prepareTracks_l() | 
|  | 1018 | mixer_state                     mMixerStatus;       // current cycle | 
|  | 1019 | mixer_state                     mPrevMixerStatus;   // previous cycle | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1020 |  | 
|  | 1021 | // FIXME move these declarations into the specific sub-class that needs them | 
|  | 1022 | // MIXER only | 
|  | 1023 | bool                            longStandbyExit; | 
|  | 1024 | uint32_t                        sleepTimeShift; | 
| Glenn Kasten | 66fcab9 | 2012-02-24 14:59:21 -0800 | [diff] [blame] | 1025 |  | 
|  | 1026 | // same as AudioFlinger::mStandbyTimeInNsecs except for DIRECT which uses a shorter value | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1027 | nsecs_t                         standbyDelay; | 
| Glenn Kasten | 66fcab9 | 2012-02-24 14:59:21 -0800 | [diff] [blame] | 1028 |  | 
|  | 1029 | // MIXER only | 
|  | 1030 | nsecs_t                         maxPeriod; | 
|  | 1031 |  | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1032 | // DUPLICATING only | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1033 | uint32_t                        writeFrames; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1034 | }; | 
|  | 1035 |  | 
|  | 1036 | class MixerThread : public PlaybackThread { | 
|  | 1037 | public: | 
| Eric Laurent | de07013 | 2010-07-13 04:45:46 -0700 | [diff] [blame] | 1038 | MixerThread (const sp<AudioFlinger>& audioFlinger, | 
| Dima Zavin | 799a70e | 2011-04-18 16:57:27 -0700 | [diff] [blame] | 1039 | AudioStreamOut* output, | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 1040 | audio_io_handle_t id, | 
| Glenn Kasten | 23bb8be | 2012-01-26 10:38:26 -0800 | [diff] [blame] | 1041 | uint32_t device, | 
|  | 1042 | type_t type = MIXER); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1043 | virtual             ~MixerThread(); | 
|  | 1044 |  | 
|  | 1045 | // Thread virtuals | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1046 |  | 
| Glenn Kasten | fff6d71 | 2012-01-12 16:38:12 -0800 | [diff] [blame] | 1047 | void        invalidateTracks(audio_stream_type_t streamType); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1048 | virtual     bool        checkForNewParameters_l(); | 
|  | 1049 | virtual     status_t    dumpInternals(int fd, const Vector<String16>& args); | 
|  | 1050 |  | 
|  | 1051 | protected: | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1052 | virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1053 | virtual     int         getTrackName_l(); | 
|  | 1054 | virtual     void        deleteTrackName_l(int name); | 
| Glenn Kasten | 0bf65bd | 2012-02-28 18:32:53 -0800 | [diff] [blame^] | 1055 | virtual     uint32_t    idleSleepTimeUs() const; | 
|  | 1056 | virtual     uint32_t    suspendSleepTimeUs() const; | 
| Glenn Kasten | 66fcab9 | 2012-02-24 14:59:21 -0800 | [diff] [blame] | 1057 | virtual     void        cacheParameters_l(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1058 |  | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1059 | // threadLoop snippets | 
|  | 1060 | virtual     void        threadLoop_mix(); | 
|  | 1061 | virtual     void        threadLoop_sleepTime(); | 
|  | 1062 |  | 
| Eric Laurent | 2774144 | 2012-01-17 19:20:12 -0800 | [diff] [blame] | 1063 | AudioMixer* mAudioMixer; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1064 | }; | 
|  | 1065 |  | 
|  | 1066 | class DirectOutputThread : public PlaybackThread { | 
|  | 1067 | public: | 
|  | 1068 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 1069 | DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, | 
|  | 1070 | audio_io_handle_t id, uint32_t device); | 
| Glenn Kasten | c19e224 | 2012-01-30 14:54:39 -0800 | [diff] [blame] | 1071 | virtual                 ~DirectOutputThread(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1072 |  | 
|  | 1073 | // Thread virtuals | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1074 |  | 
|  | 1075 | virtual     bool        checkForNewParameters_l(); | 
|  | 1076 |  | 
|  | 1077 | protected: | 
|  | 1078 | virtual     int         getTrackName_l(); | 
|  | 1079 | virtual     void        deleteTrackName_l(int name); | 
| Glenn Kasten | 0bf65bd | 2012-02-28 18:32:53 -0800 | [diff] [blame^] | 1080 | virtual     uint32_t    activeSleepTimeUs() const; | 
|  | 1081 | virtual     uint32_t    idleSleepTimeUs() const; | 
|  | 1082 | virtual     uint32_t    suspendSleepTimeUs() const; | 
| Glenn Kasten | 66fcab9 | 2012-02-24 14:59:21 -0800 | [diff] [blame] | 1083 | virtual     void        cacheParameters_l(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1084 |  | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1085 | // threadLoop snippets | 
| Glenn Kasten | 1465f0c | 2012-03-06 11:23:32 -0800 | [diff] [blame] | 1086 | virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove); | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1087 | virtual     void        threadLoop_mix(); | 
|  | 1088 | virtual     void        threadLoop_sleepTime(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1089 |  | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 1090 | // volumes last sent to audio HAL with stream->set_volume() | 
|  | 1091 | // FIXME use standard representation and names | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1092 | float mLeftVolFloat; | 
|  | 1093 | float mRightVolFloat; | 
|  | 1094 | uint16_t mLeftVolShort; | 
|  | 1095 | uint16_t mRightVolShort; | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1096 |  | 
|  | 1097 | // FIXME rename these former local variables of threadLoop to standard names | 
|  | 1098 | // next 3 were local to the while !exitingPending loop | 
|  | 1099 | bool rampVolume; | 
|  | 1100 | uint16_t leftVol; | 
|  | 1101 | uint16_t rightVol; | 
| Glenn Kasten | d4513b0 | 2012-03-06 15:52:35 -0800 | [diff] [blame] | 1102 |  | 
|  | 1103 | private: | 
| Glenn Kasten | b071e9b | 2012-03-07 17:05:59 -0800 | [diff] [blame] | 1104 | // prepareTracks_l() tells threadLoop_mix() the name of the single active track | 
|  | 1105 | sp<Track>               mActiveTrack; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1106 | }; | 
|  | 1107 |  | 
|  | 1108 | class DuplicatingThread : public MixerThread { | 
|  | 1109 | public: | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 1110 | DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread, | 
|  | 1111 | audio_io_handle_t id); | 
| Glenn Kasten | c19e224 | 2012-01-30 14:54:39 -0800 | [diff] [blame] | 1112 | virtual                 ~DuplicatingThread(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1113 |  | 
|  | 1114 | // Thread virtuals | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1115 | void        addOutputTrack(MixerThread* thread); | 
|  | 1116 | void        removeOutputTrack(MixerThread* thread); | 
| Glenn Kasten | 0bf65bd | 2012-02-28 18:32:53 -0800 | [diff] [blame^] | 1117 | uint32_t    waitTimeMs() const { return mWaitTimeMs; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1118 | protected: | 
| Glenn Kasten | 0bf65bd | 2012-02-28 18:32:53 -0800 | [diff] [blame^] | 1119 | virtual     uint32_t    activeSleepTimeUs() const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1120 |  | 
|  | 1121 | private: | 
| Glenn Kasten | e53b9ea | 2012-03-12 16:29:55 -0700 | [diff] [blame] | 1122 | bool        outputsReady(const SortedVector< sp<OutputTrack> > &outputTracks); | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1123 | protected: | 
|  | 1124 | // threadLoop snippets | 
|  | 1125 | virtual     void        threadLoop_mix(); | 
|  | 1126 | virtual     void        threadLoop_sleepTime(); | 
|  | 1127 | virtual     void        threadLoop_write(); | 
|  | 1128 | virtual     void        threadLoop_standby(); | 
| Glenn Kasten | 66fcab9 | 2012-02-24 14:59:21 -0800 | [diff] [blame] | 1129 | virtual     void        cacheParameters_l(); | 
| Glenn Kasten | 438b036 | 2012-03-06 11:24:48 -0800 | [diff] [blame] | 1130 |  | 
| Glenn Kasten | 66fcab9 | 2012-02-24 14:59:21 -0800 | [diff] [blame] | 1131 | private: | 
| Glenn Kasten | 438b036 | 2012-03-06 11:24:48 -0800 | [diff] [blame] | 1132 | // called from threadLoop, addOutputTrack, removeOutputTrack | 
|  | 1133 | virtual     void        updateWaitTime_l(); | 
| Glenn Kasten | 66fcab9 | 2012-02-24 14:59:21 -0800 | [diff] [blame] | 1134 | protected: | 
| Glenn Kasten | fa26a85 | 2012-03-06 11:28:04 -0800 | [diff] [blame] | 1135 | virtual     void        saveOutputTracks(); | 
|  | 1136 | virtual     void        clearOutputTracks(); | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1137 | private: | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1138 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1139 | uint32_t    mWaitTimeMs; | 
| Glenn Kasten | fa26a85 | 2012-03-06 11:28:04 -0800 | [diff] [blame] | 1140 | SortedVector < sp<OutputTrack> >  outputTracks; | 
|  | 1141 | SortedVector < sp<OutputTrack> >  mOutputTracks; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1142 | }; | 
|  | 1143 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 1144 | PlaybackThread *checkPlaybackThread_l(audio_io_handle_t output) const; | 
|  | 1145 | MixerThread *checkMixerThread_l(audio_io_handle_t output) const; | 
|  | 1146 | RecordThread *checkRecordThread_l(audio_io_handle_t input) const; | 
| Glenn Kasten | 6637baa | 2012-01-09 09:40:36 -0800 | [diff] [blame] | 1147 | // no range check, AudioFlinger::mLock held | 
|  | 1148 | bool streamMute_l(audio_stream_type_t stream) const | 
|  | 1149 | { return mStreamTypes[stream].mute; } | 
|  | 1150 | // no range check, doesn't check per-thread stream volume, AudioFlinger::mLock held | 
|  | 1151 | float streamVolume_l(audio_stream_type_t stream) const | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 1152 | { return mStreamTypes[stream].volume; } | 
| Glenn Kasten | b81cc8c | 2012-03-01 09:14:51 -0800 | [diff] [blame] | 1153 | void audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1154 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 1155 | // allocate an audio_io_handle_t, session ID, or effect ID | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 1156 | uint32_t nextUniqueId(); | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 1157 |  | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1158 | status_t moveEffectChain_l(int sessionId, | 
| Glenn Kasten | a111792 | 2012-01-26 10:53:32 -0800 | [diff] [blame] | 1159 | PlaybackThread *srcThread, | 
|  | 1160 | PlaybackThread *dstThread, | 
| Eric Laurent | 39e94f8 | 2010-07-28 01:32:47 -0700 | [diff] [blame] | 1161 | bool reRegister); | 
| Glenn Kasten | 02fe1bf | 2012-02-24 15:42:17 -0800 | [diff] [blame] | 1162 | // return thread associated with primary hardware device, or NULL | 
|  | 1163 | PlaybackThread *primaryPlaybackThread_l() const; | 
|  | 1164 | uint32_t primaryOutputDevice_l() const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1165 |  | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 1166 | // server side of the client's IAudioTrack | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1167 | class TrackHandle : public android::BnAudioTrack { | 
|  | 1168 | public: | 
|  | 1169 | TrackHandle(const sp<PlaybackThread::Track>& track); | 
|  | 1170 | virtual             ~TrackHandle(); | 
| Glenn Kasten | 90716c5 | 2012-01-26 13:40:12 -0800 | [diff] [blame] | 1171 | virtual sp<IMemory> getCblk() const; | 
| Glenn Kasten | 6dbc135 | 2012-02-02 10:56:47 -0800 | [diff] [blame] | 1172 | virtual status_t    start(pid_t tid); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1173 | virtual void        stop(); | 
|  | 1174 | virtual void        flush(); | 
|  | 1175 | virtual void        mute(bool); | 
|  | 1176 | virtual void        pause(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1177 | virtual status_t    attachAuxEffect(int effectId); | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 1178 | virtual status_t    allocateTimedBuffer(size_t size, | 
|  | 1179 | sp<IMemory>* buffer); | 
|  | 1180 | virtual status_t    queueTimedBuffer(const sp<IMemory>& buffer, | 
|  | 1181 | int64_t pts); | 
|  | 1182 | virtual status_t    setMediaTimeTransform(const LinearTransform& xform, | 
|  | 1183 | int target); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1184 | virtual status_t onTransact( | 
|  | 1185 | uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); | 
|  | 1186 | private: | 
| Glenn Kasten | 84afa3b | 2012-01-25 15:28:08 -0800 | [diff] [blame] | 1187 | const sp<PlaybackThread::Track> mTrack; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1188 | }; | 
|  | 1189 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1190 | void        removeClient_l(pid_t pid); | 
|  | 1191 | void        removeNotificationClient(pid_t pid); | 
|  | 1192 |  | 
|  | 1193 |  | 
|  | 1194 | // record thread | 
|  | 1195 | class RecordThread : public ThreadBase, public AudioBufferProvider | 
|  | 1196 | { | 
|  | 1197 | public: | 
|  | 1198 |  | 
|  | 1199 | // record track | 
|  | 1200 | class RecordTrack : public TrackBase { | 
|  | 1201 | public: | 
| Glenn Kasten | 9eaa557 | 2012-01-20 13:32:16 -0800 | [diff] [blame] | 1202 | RecordTrack(RecordThread *thread, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1203 | const sp<Client>& client, | 
|  | 1204 | uint32_t sampleRate, | 
| Glenn Kasten | 58f3021 | 2012-01-12 12:27:51 -0800 | [diff] [blame] | 1205 | audio_format_t format, | 
| Jean-Michel Trivi | 0d255b2 | 2011-05-24 15:53:33 -0700 | [diff] [blame] | 1206 | uint32_t channelMask, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1207 | int frameCount, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1208 | int sessionId); | 
| Glenn Kasten | c19e224 | 2012-01-30 14:54:39 -0800 | [diff] [blame] | 1209 | virtual             ~RecordTrack(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1210 |  | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 1211 | virtual status_t    start(pid_t tid, | 
|  | 1212 | AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, | 
|  | 1213 | int triggerSession = 0); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1214 | virtual void        stop(); | 
|  | 1215 |  | 
|  | 1216 | bool        overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; } | 
|  | 1217 | bool        setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; } | 
|  | 1218 |  | 
|  | 1219 | void        dump(char* buffer, size_t size); | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1220 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1221 | private: | 
| Glenn Kasten | 1998661 | 2012-03-09 12:07:30 -0800 | [diff] [blame] | 1222 | friend class AudioFlinger;  // for mState | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1223 |  | 
|  | 1224 | RecordTrack(const RecordTrack&); | 
|  | 1225 | RecordTrack& operator = (const RecordTrack&); | 
|  | 1226 |  | 
| Glenn Kasten | 01c4ebf | 2012-02-22 10:47:35 -0800 | [diff] [blame] | 1227 | // AudioBufferProvider interface | 
|  | 1228 | virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts = kInvalidPTS); | 
|  | 1229 | // releaseBuffer() not overridden | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1230 |  | 
|  | 1231 | bool                mOverflow; | 
|  | 1232 | }; | 
|  | 1233 |  | 
|  | 1234 |  | 
|  | 1235 | RecordThread(const sp<AudioFlinger>& audioFlinger, | 
| Dima Zavin | 799a70e | 2011-04-18 16:57:27 -0700 | [diff] [blame] | 1236 | AudioStreamIn *input, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1237 | uint32_t sampleRate, | 
|  | 1238 | uint32_t channels, | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 1239 | audio_io_handle_t id, | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 1240 | uint32_t device); | 
| Glenn Kasten | c19e224 | 2012-01-30 14:54:39 -0800 | [diff] [blame] | 1241 | virtual     ~RecordThread(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1242 |  | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1243 | // Thread | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1244 | virtual bool        threadLoop(); | 
| Eric Laurent | b8ba0a9 | 2011-08-07 16:32:26 -0700 | [diff] [blame] | 1245 | virtual status_t    readyToRun(); | 
| Glenn Kasten | 000f0e3 | 2012-03-01 17:10:56 -0800 | [diff] [blame] | 1246 |  | 
|  | 1247 | // RefBase | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1248 | virtual void        onFirstRef(); | 
|  | 1249 |  | 
| Glenn Kasten | e0feee3 | 2011-12-13 11:53:26 -0800 | [diff] [blame] | 1250 | virtual status_t    initCheck() const { return (mInput == NULL) ? NO_INIT : NO_ERROR; } | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 1251 | sp<AudioFlinger::RecordThread::RecordTrack>  createRecordTrack_l( | 
|  | 1252 | const sp<AudioFlinger::Client>& client, | 
|  | 1253 | uint32_t sampleRate, | 
| Glenn Kasten | 58f3021 | 2012-01-12 12:27:51 -0800 | [diff] [blame] | 1254 | audio_format_t format, | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 1255 | int channelMask, | 
|  | 1256 | int frameCount, | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 1257 | int sessionId, | 
|  | 1258 | status_t *status); | 
|  | 1259 |  | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 1260 | status_t    start(RecordTrack* recordTrack, pid_t tid, | 
|  | 1261 | AudioSystem::sync_event_t event, | 
|  | 1262 | int triggerSession); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1263 | void        stop(RecordTrack* recordTrack); | 
|  | 1264 | status_t    dump(int fd, const Vector<String16>& args); | 
| Glenn Kasten | aed850d | 2012-01-26 09:46:34 -0800 | [diff] [blame] | 1265 | AudioStreamIn* getInput() const; | 
| Eric Laurent | b8ba0a9 | 2011-08-07 16:32:26 -0700 | [diff] [blame] | 1266 | AudioStreamIn* clearInput(); | 
| Glenn Kasten | 0bf65bd | 2012-02-28 18:32:53 -0800 | [diff] [blame^] | 1267 | virtual audio_stream_t* stream() const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1268 |  | 
| Glenn Kasten | 01c4ebf | 2012-02-22 10:47:35 -0800 | [diff] [blame] | 1269 | // AudioBufferProvider interface | 
|  | 1270 | virtual status_t    getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1271 | virtual void        releaseBuffer(AudioBufferProvider::Buffer* buffer); | 
| Glenn Kasten | 01c4ebf | 2012-02-22 10:47:35 -0800 | [diff] [blame] | 1272 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1273 | virtual bool        checkForNewParameters_l(); | 
|  | 1274 | virtual String8     getParameters(const String8& keys); | 
|  | 1275 | virtual void        audioConfigChanged_l(int event, int param = 0); | 
|  | 1276 | void        readInputParameters(); | 
|  | 1277 | virtual unsigned int  getInputFramesLost(); | 
|  | 1278 |  | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 1279 | virtual status_t addEffectChain_l(const sp<EffectChain>& chain); | 
|  | 1280 | virtual size_t removeEffectChain_l(const sp<EffectChain>& chain); | 
|  | 1281 | virtual uint32_t hasAudioSession(int sessionId); | 
| Eric Laurent | 59bd0da | 2011-08-01 09:52:20 -0700 | [diff] [blame] | 1282 | RecordTrack* track(); | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 1283 |  | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 1284 | virtual status_t setSyncEvent(const sp<SyncEvent>& event); | 
|  | 1285 | virtual bool     isValidSyncEvent(const sp<SyncEvent>& event); | 
|  | 1286 |  | 
|  | 1287 | static void syncStartEventCallback(const wp<SyncEvent>& event); | 
|  | 1288 | void handleSyncStartEvent(const sp<SyncEvent>& event); | 
|  | 1289 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1290 | private: | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 1291 | void clearSyncStartEvent(); | 
|  | 1292 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1293 | RecordThread(); | 
| Dima Zavin | 799a70e | 2011-04-18 16:57:27 -0700 | [diff] [blame] | 1294 | AudioStreamIn                       *mInput; | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 1295 | RecordTrack*                        mTrack; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1296 | sp<RecordTrack>                     mActiveTrack; | 
|  | 1297 | Condition                           mStartStopCond; | 
|  | 1298 | AudioResampler                      *mResampler; | 
|  | 1299 | int32_t                             *mRsmpOutBuffer; | 
|  | 1300 | int16_t                             *mRsmpInBuffer; | 
|  | 1301 | size_t                              mRsmpInIndex; | 
|  | 1302 | size_t                              mInputBytes; | 
| Glenn Kasten | 84afa3b | 2012-01-25 15:28:08 -0800 | [diff] [blame] | 1303 | const int                           mReqChannelCount; | 
|  | 1304 | const uint32_t                      mReqSampleRate; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1305 | ssize_t                             mBytesRead; | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 1306 | // sync event triggering actual audio capture. Frames read before this event will | 
|  | 1307 | // be dropped and therefore not read by the application. | 
|  | 1308 | sp<SyncEvent>                       mSyncStartEvent; | 
|  | 1309 | // number of captured frames to drop after the start sync event has been received. | 
|  | 1310 | ssize_t                             mFramestoDrop; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1311 | }; | 
|  | 1312 |  | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 1313 | // server side of the client's IAudioRecord | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1314 | class RecordHandle : public android::BnAudioRecord { | 
|  | 1315 | public: | 
|  | 1316 | RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack); | 
|  | 1317 | virtual             ~RecordHandle(); | 
| Glenn Kasten | 90716c5 | 2012-01-26 13:40:12 -0800 | [diff] [blame] | 1318 | virtual sp<IMemory> getCblk() const; | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 1319 | virtual status_t    start(pid_t tid, int event, int triggerSession); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1320 | virtual void        stop(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1321 | virtual status_t onTransact( | 
|  | 1322 | uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); | 
|  | 1323 | private: | 
| Glenn Kasten | 84afa3b | 2012-01-25 15:28:08 -0800 | [diff] [blame] | 1324 | const sp<RecordThread::RecordTrack> mRecordTrack; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1325 | }; | 
|  | 1326 |  | 
|  | 1327 | //--- Audio Effect Management | 
|  | 1328 |  | 
|  | 1329 | // EffectModule and EffectChain classes both have their own mutex to protect | 
|  | 1330 | // state changes or resource modifications. Always respect the following order | 
|  | 1331 | // if multiple mutexes must be acquired to avoid cross deadlock: | 
|  | 1332 | // AudioFlinger -> ThreadBase -> EffectChain -> EffectModule | 
|  | 1333 |  | 
|  | 1334 | // The EffectModule class is a wrapper object controlling the effect engine implementation | 
|  | 1335 | // in the effect library. It prevents concurrent calls to process() and command() functions | 
|  | 1336 | // from different client threads. It keeps a list of EffectHandle objects corresponding | 
|  | 1337 | // to all client applications using this effect and notifies applications of effect state, | 
|  | 1338 | // control or parameter changes. It manages the activation state machine to send appropriate | 
|  | 1339 | // reset, enable, disable commands to effect engine and provide volume | 
|  | 1340 | // ramping when effects are activated/deactivated. | 
|  | 1341 | // When controlling an auxiliary effect, the EffectModule also provides an input buffer used by | 
|  | 1342 | // the attached track(s) to accumulate their auxiliary channel. | 
|  | 1343 | class EffectModule: public RefBase { | 
|  | 1344 | public: | 
| Glenn Kasten | 9eaa557 | 2012-01-20 13:32:16 -0800 | [diff] [blame] | 1345 | EffectModule(ThreadBase *thread, | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1346 | const wp<AudioFlinger::EffectChain>& chain, | 
|  | 1347 | effect_descriptor_t *desc, | 
|  | 1348 | int id, | 
|  | 1349 | int sessionId); | 
| Glenn Kasten | c19e224 | 2012-01-30 14:54:39 -0800 | [diff] [blame] | 1350 | virtual ~EffectModule(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1351 |  | 
|  | 1352 | enum effect_state { | 
|  | 1353 | IDLE, | 
|  | 1354 | RESTART, | 
|  | 1355 | STARTING, | 
|  | 1356 | ACTIVE, | 
|  | 1357 | STOPPING, | 
| Eric Laurent | ec437d8 | 2011-07-26 20:54:46 -0700 | [diff] [blame] | 1358 | STOPPED, | 
|  | 1359 | DESTROYED | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1360 | }; | 
|  | 1361 |  | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 1362 | int         id() const { return mId; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1363 | void process(); | 
|  | 1364 | void updateState(); | 
| Eric Laurent | 25f4395 | 2010-07-28 05:40:18 -0700 | [diff] [blame] | 1365 | status_t command(uint32_t cmdCode, | 
|  | 1366 | uint32_t cmdSize, | 
|  | 1367 | void *pCmdData, | 
|  | 1368 | uint32_t *replySize, | 
|  | 1369 | void *pReplyData); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1370 |  | 
|  | 1371 | void reset_l(); | 
|  | 1372 | status_t configure(); | 
|  | 1373 | status_t init(); | 
| Glenn Kasten | 28243dd | 2012-01-26 13:43:46 -0800 | [diff] [blame] | 1374 | effect_state state() const { | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1375 | return mState; | 
|  | 1376 | } | 
|  | 1377 | uint32_t status() { | 
|  | 1378 | return mStatus; | 
|  | 1379 | } | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 1380 | int sessionId() const { | 
| Eric Laurent | de07013 | 2010-07-13 04:45:46 -0700 | [diff] [blame] | 1381 | return mSessionId; | 
|  | 1382 | } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1383 | status_t    setEnabled(bool enabled); | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 1384 | bool isEnabled() const; | 
|  | 1385 | bool isProcessEnabled() const; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1386 |  | 
|  | 1387 | void        setInBuffer(int16_t *buffer) { mConfig.inputCfg.buffer.s16 = buffer; } | 
|  | 1388 | int16_t     *inBuffer() { return mConfig.inputCfg.buffer.s16; } | 
|  | 1389 | void        setOutBuffer(int16_t *buffer) { mConfig.outputCfg.buffer.s16 = buffer; } | 
|  | 1390 | int16_t     *outBuffer() { return mConfig.outputCfg.buffer.s16; } | 
| Eric Laurent | de07013 | 2010-07-13 04:45:46 -0700 | [diff] [blame] | 1391 | void        setChain(const wp<EffectChain>& chain) { mChain = chain; } | 
|  | 1392 | void        setThread(const wp<ThreadBase>& thread) { mThread = thread; } | 
| Glenn Kasten | 84afa3b | 2012-01-25 15:28:08 -0800 | [diff] [blame] | 1393 | const wp<ThreadBase>& thread() { return mThread; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1394 |  | 
| Glenn Kasten | 435dbe6 | 2012-01-30 10:15:48 -0800 | [diff] [blame] | 1395 | status_t addHandle(const sp<EffectHandle>& handle); | 
| Glenn Kasten | 58123c3 | 2012-02-03 10:32:24 -0800 | [diff] [blame] | 1396 | void disconnect(const wp<EffectHandle>& handle, bool unpinIfLast); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1397 | size_t removeHandle (const wp<EffectHandle>& handle); | 
|  | 1398 |  | 
|  | 1399 | effect_descriptor_t& desc() { return mDescriptor; } | 
|  | 1400 | wp<EffectChain>&     chain() { return mChain; } | 
|  | 1401 |  | 
|  | 1402 | status_t         setDevice(uint32_t device); | 
|  | 1403 | status_t         setVolume(uint32_t *left, uint32_t *right, bool controller); | 
| Glenn Kasten | f78aee7 | 2012-01-04 11:00:47 -0800 | [diff] [blame] | 1404 | status_t         setMode(audio_mode_t mode); | 
| Eric Laurent | ec35a14 | 2011-10-05 17:42:25 -0700 | [diff] [blame] | 1405 | status_t         start(); | 
| Eric Laurent | ec437d8 | 2011-07-26 20:54:46 -0700 | [diff] [blame] | 1406 | status_t         stop(); | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1407 | void             setSuspended(bool suspended); | 
| Glenn Kasten | a3a8548 | 2012-01-04 11:01:11 -0800 | [diff] [blame] | 1408 | bool             suspended() const; | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1409 |  | 
|  | 1410 | sp<EffectHandle> controlHandle(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1411 |  | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 1412 | bool             isPinned() const { return mPinned; } | 
| Marco Nelissen | 3a34bef | 2011-08-02 13:33:41 -0700 | [diff] [blame] | 1413 | void             unPin() { mPinned = false; } | 
|  | 1414 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1415 | status_t         dump(int fd, const Vector<String16>& args); | 
|  | 1416 |  | 
|  | 1417 | protected: | 
| Glenn Kasten | 1998661 | 2012-03-09 12:07:30 -0800 | [diff] [blame] | 1418 | friend class AudioFlinger;      // for mHandles | 
| Marco Nelissen | 3a34bef | 2011-08-02 13:33:41 -0700 | [diff] [blame] | 1419 | bool                mPinned; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1420 |  | 
|  | 1421 | // Maximum time allocated to effect engines to complete the turn off sequence | 
|  | 1422 | static const uint32_t MAX_DISABLE_TIME_MS = 10000; | 
|  | 1423 |  | 
|  | 1424 | EffectModule(const EffectModule&); | 
|  | 1425 | EffectModule& operator = (const EffectModule&); | 
|  | 1426 |  | 
|  | 1427 | status_t start_l(); | 
|  | 1428 | status_t stop_l(); | 
|  | 1429 |  | 
| Glenn Kasten | a3a8548 | 2012-01-04 11:01:11 -0800 | [diff] [blame] | 1430 | mutable Mutex               mLock;      // mutex for process, commands and handles list protection | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1431 | wp<ThreadBase>      mThread;    // parent thread | 
|  | 1432 | wp<EffectChain>     mChain;     // parent effect chain | 
|  | 1433 | int                 mId;        // this instance unique ID | 
|  | 1434 | int                 mSessionId; // audio session ID | 
|  | 1435 | effect_descriptor_t mDescriptor;// effect descriptor received from effect engine | 
|  | 1436 | effect_config_t     mConfig;    // input and output audio configuration | 
| Eric Laurent | e1315cf | 2011-05-17 19:16:02 -0700 | [diff] [blame] | 1437 | effect_handle_t  mEffectInterface; // Effect module C API | 
| Glenn Kasten | 28243dd | 2012-01-26 13:43:46 -0800 | [diff] [blame] | 1438 | status_t            mStatus;    // initialization status | 
|  | 1439 | effect_state        mState;     // current activation state | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1440 | Vector< wp<EffectHandle> > mHandles;    // list of client handles | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 1441 | // First handle in mHandles has highest priority and controls the effect module | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1442 | uint32_t mMaxDisableWaitCnt;    // maximum grace period before forcing an effect off after | 
|  | 1443 | // sending disable command. | 
|  | 1444 | uint32_t mDisableWaitCnt;       // current process() calls count during disable period. | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1445 | bool     mSuspended;            // effect is suspended: temporarily disabled by framework | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1446 | }; | 
|  | 1447 |  | 
|  | 1448 | // The EffectHandle class implements the IEffect interface. It provides resources | 
|  | 1449 | // to receive parameter updates, keeps track of effect control | 
|  | 1450 | // ownership and state and has a pointer to the EffectModule object it is controlling. | 
|  | 1451 | // There is one EffectHandle object for each application controlling (or using) | 
|  | 1452 | // an effect module. | 
|  | 1453 | // The EffectHandle is obtained by calling AudioFlinger::createEffect(). | 
|  | 1454 | class EffectHandle: public android::BnEffect { | 
|  | 1455 | public: | 
|  | 1456 |  | 
|  | 1457 | EffectHandle(const sp<EffectModule>& effect, | 
|  | 1458 | const sp<AudioFlinger::Client>& client, | 
|  | 1459 | const sp<IEffectClient>& effectClient, | 
|  | 1460 | int32_t priority); | 
|  | 1461 | virtual ~EffectHandle(); | 
|  | 1462 |  | 
|  | 1463 | // IEffect | 
|  | 1464 | virtual status_t enable(); | 
|  | 1465 | virtual status_t disable(); | 
| Eric Laurent | 25f4395 | 2010-07-28 05:40:18 -0700 | [diff] [blame] | 1466 | virtual status_t command(uint32_t cmdCode, | 
|  | 1467 | uint32_t cmdSize, | 
|  | 1468 | void *pCmdData, | 
|  | 1469 | uint32_t *replySize, | 
|  | 1470 | void *pReplyData); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1471 | virtual void disconnect(); | 
| Glenn Kasten | 58123c3 | 2012-02-03 10:32:24 -0800 | [diff] [blame] | 1472 | private: | 
|  | 1473 | void disconnect(bool unpinIfLast); | 
|  | 1474 | public: | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 1475 | virtual sp<IMemory> getCblk() const { return mCblkMemory; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1476 | virtual status_t onTransact(uint32_t code, const Parcel& data, | 
|  | 1477 | Parcel* reply, uint32_t flags); | 
|  | 1478 |  | 
|  | 1479 |  | 
|  | 1480 | // Give or take control of effect module | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1481 | // - hasControl: true if control is given, false if removed | 
|  | 1482 | // - signal: true client app should be signaled of change, false otherwise | 
|  | 1483 | // - enabled: state of the effect when control is passed | 
|  | 1484 | void setControl(bool hasControl, bool signal, bool enabled); | 
| Eric Laurent | 25f4395 | 2010-07-28 05:40:18 -0700 | [diff] [blame] | 1485 | void commandExecuted(uint32_t cmdCode, | 
|  | 1486 | uint32_t cmdSize, | 
|  | 1487 | void *pCmdData, | 
|  | 1488 | uint32_t replySize, | 
|  | 1489 | void *pReplyData); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1490 | void setEnabled(bool enabled); | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 1491 | bool enabled() const { return mEnabled; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1492 |  | 
|  | 1493 | // Getters | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 1494 | int id() const { return mEffect->id(); } | 
|  | 1495 | int priority() const { return mPriority; } | 
|  | 1496 | bool hasControl() const { return mHasControl; } | 
|  | 1497 | sp<EffectModule> effect() const { return mEffect; } | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1498 |  | 
|  | 1499 | void dump(char* buffer, size_t size); | 
|  | 1500 |  | 
|  | 1501 | protected: | 
| Glenn Kasten | 1998661 | 2012-03-09 12:07:30 -0800 | [diff] [blame] | 1502 | friend class AudioFlinger;          // for mEffect, mHasControl, mEnabled | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1503 | EffectHandle(const EffectHandle&); | 
|  | 1504 | EffectHandle& operator =(const EffectHandle&); | 
|  | 1505 |  | 
|  | 1506 | sp<EffectModule> mEffect;           // pointer to controlled EffectModule | 
|  | 1507 | sp<IEffectClient> mEffectClient;    // callback interface for client notifications | 
| Glenn Kasten | 98ec94c | 2012-01-25 14:28:29 -0800 | [diff] [blame] | 1508 | /*const*/ sp<Client> mClient;       // client for shared memory allocation, see disconnect() | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1509 | sp<IMemory>         mCblkMemory;    // shared memory for control block | 
|  | 1510 | effect_param_cblk_t* mCblk;         // control block for deferred parameter setting via shared memory | 
|  | 1511 | uint8_t*            mBuffer;        // pointer to parameter area in shared memory | 
|  | 1512 | int mPriority;                      // client application priority to control the effect | 
|  | 1513 | bool mHasControl;                   // true if this handle is controlling the effect | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1514 | bool mEnabled;                      // cached enable state: needed when the effect is | 
|  | 1515 | // restored after being suspended | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1516 | }; | 
|  | 1517 |  | 
|  | 1518 | // the EffectChain class represents a group of effects associated to one audio session. | 
|  | 1519 | // There can be any number of EffectChain objects per output mixer thread (PlaybackThread). | 
|  | 1520 | // The EffecChain with session ID 0 contains global effects applied to the output mix. | 
|  | 1521 | // Effects in this chain can be insert or auxiliary. Effects in other chains (attached to tracks) | 
|  | 1522 | // are insert only. The EffectChain maintains an ordered list of effect module, the order corresponding | 
|  | 1523 | // in the effect process order. When attached to a track (session ID != 0), it also provide it's own | 
|  | 1524 | // input buffer used by the track as accumulation buffer. | 
|  | 1525 | class EffectChain: public RefBase { | 
|  | 1526 | public: | 
|  | 1527 | EffectChain(const wp<ThreadBase>& wThread, int sessionId); | 
| Glenn Kasten | 9eaa557 | 2012-01-20 13:32:16 -0800 | [diff] [blame] | 1528 | EffectChain(ThreadBase *thread, int sessionId); | 
| Glenn Kasten | c19e224 | 2012-01-30 14:54:39 -0800 | [diff] [blame] | 1529 | virtual ~EffectChain(); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1530 |  | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1531 | // special key used for an entry in mSuspendedEffects keyed vector | 
|  | 1532 | // corresponding to a suspend all request. | 
|  | 1533 | static const int        kKeyForSuspendAll = 0; | 
|  | 1534 |  | 
| Eric Laurent | 544fe9b | 2011-11-11 15:42:52 -0800 | [diff] [blame] | 1535 | // minimum duration during which we force calling effect process when last track on | 
|  | 1536 | // a session is stopped or removed to allow effect tail to be rendered | 
|  | 1537 | static const int        kProcessTailDurationMs = 1000; | 
|  | 1538 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1539 | void process_l(); | 
|  | 1540 |  | 
|  | 1541 | void lock() { | 
|  | 1542 | mLock.lock(); | 
|  | 1543 | } | 
|  | 1544 | void unlock() { | 
|  | 1545 | mLock.unlock(); | 
|  | 1546 | } | 
|  | 1547 |  | 
| Eric Laurent | de07013 | 2010-07-13 04:45:46 -0700 | [diff] [blame] | 1548 | status_t addEffect_l(const sp<EffectModule>& handle); | 
| Eric Laurent | cab1124 | 2010-07-15 12:50:15 -0700 | [diff] [blame] | 1549 | size_t removeEffect_l(const sp<EffectModule>& handle); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1550 |  | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 1551 | int sessionId() const { return mSessionId; } | 
| Eric Laurent | 7c7f10b | 2011-06-17 21:29:58 -0700 | [diff] [blame] | 1552 | void setSessionId(int sessionId) { mSessionId = sessionId; } | 
| Eric Laurent | de07013 | 2010-07-13 04:45:46 -0700 | [diff] [blame] | 1553 |  | 
| Eric Laurent | cab1124 | 2010-07-15 12:50:15 -0700 | [diff] [blame] | 1554 | sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor); | 
|  | 1555 | sp<EffectModule> getEffectFromId_l(int id); | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1556 | sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type); | 
| Eric Laurent | cab1124 | 2010-07-15 12:50:15 -0700 | [diff] [blame] | 1557 | bool setVolume_l(uint32_t *left, uint32_t *right); | 
|  | 1558 | void setDevice_l(uint32_t device); | 
| Glenn Kasten | f78aee7 | 2012-01-04 11:00:47 -0800 | [diff] [blame] | 1559 | void setMode_l(audio_mode_t mode); | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1560 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1561 | void setInBuffer(int16_t *buffer, bool ownsBuffer = false) { | 
|  | 1562 | mInBuffer = buffer; | 
|  | 1563 | mOwnInBuffer = ownsBuffer; | 
|  | 1564 | } | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 1565 | int16_t *inBuffer() const { | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1566 | return mInBuffer; | 
|  | 1567 | } | 
|  | 1568 | void setOutBuffer(int16_t *buffer) { | 
|  | 1569 | mOutBuffer = buffer; | 
|  | 1570 | } | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 1571 | int16_t *outBuffer() const { | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1572 | return mOutBuffer; | 
|  | 1573 | } | 
|  | 1574 |  | 
| Eric Laurent | b469b94 | 2011-05-09 12:09:06 -0700 | [diff] [blame] | 1575 | void incTrackCnt() { android_atomic_inc(&mTrackCnt); } | 
|  | 1576 | void decTrackCnt() { android_atomic_dec(&mTrackCnt); } | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 1577 | int32_t trackCnt() const { return mTrackCnt;} | 
| Eric Laurent | b469b94 | 2011-05-09 12:09:06 -0700 | [diff] [blame] | 1578 |  | 
| Eric Laurent | 544fe9b | 2011-11-11 15:42:52 -0800 | [diff] [blame] | 1579 | void incActiveTrackCnt() { android_atomic_inc(&mActiveTrackCnt); | 
|  | 1580 | mTailBufferCount = mMaxTailBuffers; } | 
| Eric Laurent | b469b94 | 2011-05-09 12:09:06 -0700 | [diff] [blame] | 1581 | void decActiveTrackCnt() { android_atomic_dec(&mActiveTrackCnt); } | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 1582 | int32_t activeTrackCnt() const { return mActiveTrackCnt;} | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1583 |  | 
| Glenn Kasten | c59c004 | 2012-02-02 14:06:11 -0800 | [diff] [blame] | 1584 | uint32_t strategy() const { return mStrategy; } | 
| Eric Laurent | de07013 | 2010-07-13 04:45:46 -0700 | [diff] [blame] | 1585 | void setStrategy(uint32_t strategy) | 
| Glenn Kasten | e53b9ea | 2012-03-12 16:29:55 -0700 | [diff] [blame] | 1586 | { mStrategy = strategy; } | 
| Eric Laurent | de07013 | 2010-07-13 04:45:46 -0700 | [diff] [blame] | 1587 |  | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1588 | // suspend effect of the given type | 
|  | 1589 | void setEffectSuspended_l(const effect_uuid_t *type, | 
|  | 1590 | bool suspend); | 
|  | 1591 | // suspend all eligible effects | 
|  | 1592 | void setEffectSuspendedAll_l(bool suspend); | 
|  | 1593 | // check if effects should be suspend or restored when a given effect is enable or disabled | 
| Eric Laurent | a85a74a | 2011-10-19 11:44:54 -0700 | [diff] [blame] | 1594 | void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect, | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1595 | bool enabled); | 
|  | 1596 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1597 | status_t dump(int fd, const Vector<String16>& args); | 
|  | 1598 |  | 
|  | 1599 | protected: | 
| Glenn Kasten | 1998661 | 2012-03-09 12:07:30 -0800 | [diff] [blame] | 1600 | friend class AudioFlinger;  // for mThread, mEffects | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1601 | EffectChain(const EffectChain&); | 
|  | 1602 | EffectChain& operator =(const EffectChain&); | 
|  | 1603 |  | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1604 | class SuspendedEffectDesc : public RefBase { | 
|  | 1605 | public: | 
|  | 1606 | SuspendedEffectDesc() : mRefCount(0) {} | 
|  | 1607 |  | 
|  | 1608 | int mRefCount; | 
|  | 1609 | effect_uuid_t mType; | 
|  | 1610 | wp<EffectModule> mEffect; | 
|  | 1611 | }; | 
|  | 1612 |  | 
|  | 1613 | // get a list of effect modules to suspend when an effect of the type | 
|  | 1614 | // passed is enabled. | 
| Glenn Kasten | d053971 | 2012-01-30 12:56:03 -0800 | [diff] [blame] | 1615 | void                       getSuspendEligibleEffects(Vector< sp<EffectModule> > &effects); | 
|  | 1616 |  | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1617 | // get an effect module if it is currently enable | 
|  | 1618 | sp<EffectModule> getEffectIfEnabled(const effect_uuid_t *type); | 
| Eric Laurent | db7c079 | 2011-08-10 10:37:50 -0700 | [diff] [blame] | 1619 | // true if the effect whose descriptor is passed can be suspended | 
|  | 1620 | // OEMs can modify the rules implemented in this method to exclude specific effect | 
|  | 1621 | // types or implementations from the suspend/restore mechanism. | 
|  | 1622 | bool isEffectEligibleForSuspend(const effect_descriptor_t& desc); | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1623 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1624 | wp<ThreadBase> mThread;     // parent mixer thread | 
|  | 1625 | Mutex mLock;                // mutex protecting effect list | 
| Glenn Kasten | e53b9ea | 2012-03-12 16:29:55 -0700 | [diff] [blame] | 1626 | Vector< sp<EffectModule> > mEffects; // list of effect modules | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1627 | int mSessionId;             // audio session ID | 
|  | 1628 | int16_t *mInBuffer;         // chain input buffer | 
|  | 1629 | int16_t *mOutBuffer;        // chain output buffer | 
| Eric Laurent | b469b94 | 2011-05-09 12:09:06 -0700 | [diff] [blame] | 1630 | volatile int32_t mActiveTrackCnt;  // number of active tracks connected | 
|  | 1631 | volatile int32_t mTrackCnt;        // number of tracks connected | 
| Eric Laurent | 544fe9b | 2011-11-11 15:42:52 -0800 | [diff] [blame] | 1632 | int32_t mTailBufferCount;   // current effect tail buffer count | 
|  | 1633 | int32_t mMaxTailBuffers;    // maximum effect tail buffers | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1634 | bool mOwnInBuffer;          // true if the chain owns its input buffer | 
| Eric Laurent | cab1124 | 2010-07-15 12:50:15 -0700 | [diff] [blame] | 1635 | int mVolumeCtrlIdx;         // index of insert effect having control over volume | 
|  | 1636 | uint32_t mLeftVolume;       // previous volume on left channel | 
|  | 1637 | uint32_t mRightVolume;      // previous volume on right channel | 
| Eric Laurent | f997cab | 2010-07-19 06:24:46 -0700 | [diff] [blame] | 1638 | uint32_t mNewLeftVolume;       // new volume on left channel | 
|  | 1639 | uint32_t mNewRightVolume;      // new volume on right channel | 
| Eric Laurent | de07013 | 2010-07-13 04:45:46 -0700 | [diff] [blame] | 1640 | uint32_t mStrategy; // strategy for this effect chain | 
| Glenn Kasten | 17a736c | 2012-02-14 08:52:15 -0800 | [diff] [blame] | 1641 | // mSuspendedEffects lists all effects currently suspended in the chain. | 
|  | 1642 | // Use effect type UUID timelow field as key. There is no real risk of identical | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1643 | // timeLow fields among effect type UUIDs. | 
| Glenn Kasten | 17a736c | 2012-02-14 08:52:15 -0800 | [diff] [blame] | 1644 | // Updated by updateSuspendedSessions_l() only. | 
| Eric Laurent | 59255e4 | 2011-07-27 19:49:51 -0700 | [diff] [blame] | 1645 | KeyedVector< int, sp<SuspendedEffectDesc> > mSuspendedEffects; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1646 | }; | 
|  | 1647 |  | 
| Glenn Kasten | aed850d | 2012-01-26 09:46:34 -0800 | [diff] [blame] | 1648 | // AudioStreamOut and AudioStreamIn are immutable, so their fields are const. | 
|  | 1649 | // For emphasis, we could also make all pointers to them be "const *", | 
|  | 1650 | // but that would clutter the code unnecessarily. | 
|  | 1651 |  | 
| Dima Zavin | 799a70e | 2011-04-18 16:57:27 -0700 | [diff] [blame] | 1652 | struct AudioStreamOut { | 
| Glenn Kasten | aed850d | 2012-01-26 09:46:34 -0800 | [diff] [blame] | 1653 | audio_hw_device_t*  const hwDev; | 
|  | 1654 | audio_stream_out_t* const stream; | 
| Dima Zavin | 799a70e | 2011-04-18 16:57:27 -0700 | [diff] [blame] | 1655 |  | 
|  | 1656 | AudioStreamOut(audio_hw_device_t *dev, audio_stream_out_t *out) : | 
|  | 1657 | hwDev(dev), stream(out) {} | 
|  | 1658 | }; | 
|  | 1659 |  | 
|  | 1660 | struct AudioStreamIn { | 
| Glenn Kasten | aed850d | 2012-01-26 09:46:34 -0800 | [diff] [blame] | 1661 | audio_hw_device_t* const hwDev; | 
|  | 1662 | audio_stream_in_t* const stream; | 
| Dima Zavin | 799a70e | 2011-04-18 16:57:27 -0700 | [diff] [blame] | 1663 |  | 
|  | 1664 | AudioStreamIn(audio_hw_device_t *dev, audio_stream_in_t *in) : | 
|  | 1665 | hwDev(dev), stream(in) {} | 
|  | 1666 | }; | 
|  | 1667 |  | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 1668 | // for mAudioSessionRefs only | 
| Marco Nelissen | 3a34bef | 2011-08-02 13:33:41 -0700 | [diff] [blame] | 1669 | struct AudioSessionRef { | 
| Glenn Kasten | 012ca6b | 2012-03-06 11:22:01 -0800 | [diff] [blame] | 1670 | AudioSessionRef(int sessionid, pid_t pid) : | 
|  | 1671 | mSessionid(sessionid), mPid(pid), mCnt(1) {} | 
|  | 1672 | const int   mSessionid; | 
|  | 1673 | const pid_t mPid; | 
|  | 1674 | int         mCnt; | 
| Marco Nelissen | 3a34bef | 2011-08-02 13:33:41 -0700 | [diff] [blame] | 1675 | }; | 
|  | 1676 |  | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 1677 | enum master_volume_support { | 
|  | 1678 | // MVS_NONE: | 
|  | 1679 | // Audio HAL has no support for master volume, either setting or | 
|  | 1680 | // getting.  All master volume control must be implemented in SW by the | 
|  | 1681 | // AudioFlinger mixing core. | 
|  | 1682 | MVS_NONE, | 
|  | 1683 |  | 
|  | 1684 | // MVS_SETONLY: | 
|  | 1685 | // Audio HAL has support for setting master volume, but not for getting | 
|  | 1686 | // master volume (original HAL design did not include a getter). | 
|  | 1687 | // AudioFlinger needs to keep track of the last set master volume in | 
|  | 1688 | // addition to needing to set an initial, default, master volume at HAL | 
|  | 1689 | // load time. | 
|  | 1690 | MVS_SETONLY, | 
|  | 1691 |  | 
|  | 1692 | // MVS_FULL: | 
|  | 1693 | // Audio HAL has support both for setting and getting master volume. | 
|  | 1694 | // AudioFlinger should send all set and get master volume requests | 
|  | 1695 | // directly to the HAL. | 
|  | 1696 | MVS_FULL, | 
|  | 1697 | }; | 
|  | 1698 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1699 | mutable     Mutex                               mLock; | 
|  | 1700 |  | 
| Glenn Kasten | 98ec94c | 2012-01-25 14:28:29 -0800 | [diff] [blame] | 1701 | DefaultKeyedVector< pid_t, wp<Client> >     mClients;   // see ~Client() | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1702 |  | 
|  | 1703 | mutable     Mutex                   mHardwareLock; | 
| Glenn Kasten | 2b213bc | 2012-02-02 14:05:20 -0800 | [diff] [blame] | 1704 |  | 
|  | 1705 | // These two fields are immutable after onFirstRef(), so no lock needed to access | 
|  | 1706 | audio_hw_device_t*                  mPrimaryHardwareDev; // mAudioHwDevs[0] or NULL | 
| Dima Zavin | 799a70e | 2011-04-18 16:57:27 -0700 | [diff] [blame] | 1707 | Vector<audio_hw_device_t*>          mAudioHwDevs; | 
| Glenn Kasten | 2f732eb | 2012-01-26 09:48:03 -0800 | [diff] [blame] | 1708 |  | 
| Glenn Kasten | 8abf44d | 2012-02-02 14:16:03 -0800 | [diff] [blame] | 1709 | // for dump, indicates which hardware operation is currently in progress (but not stream ops) | 
| Glenn Kasten | 2f732eb | 2012-01-26 09:48:03 -0800 | [diff] [blame] | 1710 | enum hardware_call_state { | 
| Glenn Kasten | 8abf44d | 2012-02-02 14:16:03 -0800 | [diff] [blame] | 1711 | AUDIO_HW_IDLE = 0,              // no operation in progress | 
|  | 1712 | AUDIO_HW_INIT,                  // init_check | 
|  | 1713 | AUDIO_HW_OUTPUT_OPEN,           // open_output_stream | 
|  | 1714 | AUDIO_HW_OUTPUT_CLOSE,          // unused | 
|  | 1715 | AUDIO_HW_INPUT_OPEN,            // unused | 
|  | 1716 | AUDIO_HW_INPUT_CLOSE,           // unused | 
|  | 1717 | AUDIO_HW_STANDBY,               // unused | 
|  | 1718 | AUDIO_HW_SET_MASTER_VOLUME,     // set_master_volume | 
|  | 1719 | AUDIO_HW_GET_ROUTING,           // unused | 
|  | 1720 | AUDIO_HW_SET_ROUTING,           // unused | 
|  | 1721 | AUDIO_HW_GET_MODE,              // unused | 
|  | 1722 | AUDIO_HW_SET_MODE,              // set_mode | 
|  | 1723 | AUDIO_HW_GET_MIC_MUTE,          // get_mic_mute | 
|  | 1724 | AUDIO_HW_SET_MIC_MUTE,          // set_mic_mute | 
|  | 1725 | AUDIO_HW_SET_VOICE_VOLUME,      // set_voice_volume | 
|  | 1726 | AUDIO_HW_SET_PARAMETER,         // set_parameters | 
|  | 1727 | AUDIO_HW_GET_INPUT_BUFFER_SIZE, // get_input_buffer_size | 
|  | 1728 | AUDIO_HW_GET_MASTER_VOLUME,     // get_master_volume | 
|  | 1729 | AUDIO_HW_GET_PARAMETER,         // get_parameters | 
| Glenn Kasten | 2f732eb | 2012-01-26 09:48:03 -0800 | [diff] [blame] | 1730 | }; | 
|  | 1731 |  | 
| Glenn Kasten | a4454b4 | 2012-01-04 11:02:33 -0800 | [diff] [blame] | 1732 | mutable     hardware_call_state                 mHardwareStatus;    // for dump only | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1733 |  | 
|  | 1734 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 1735 | DefaultKeyedVector< audio_io_handle_t, sp<PlaybackThread> >  mPlaybackThreads; | 
| Glenn Kasten | b7bf796 | 2012-02-08 12:36:25 -0800 | [diff] [blame] | 1736 | stream_type_t                       mStreamTypes[AUDIO_STREAM_CNT]; | 
| Glenn Kasten | 9806710 | 2011-12-13 11:47:54 -0800 | [diff] [blame] | 1737 |  | 
|  | 1738 | // both are protected by mLock | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1739 | float                               mMasterVolume; | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 1740 | float                               mMasterVolumeSW; | 
|  | 1741 | master_volume_support               mMasterVolumeSupportLvl; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1742 | bool                                mMasterMute; | 
|  | 1743 |  | 
| Glenn Kasten | 72ef00d | 2012-01-17 11:09:42 -0800 | [diff] [blame] | 1744 | DefaultKeyedVector< audio_io_handle_t, sp<RecordThread> >    mRecordThreads; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1745 |  | 
|  | 1746 | DefaultKeyedVector< pid_t, sp<NotificationClient> >    mNotificationClients; | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 1747 | volatile int32_t                    mNextUniqueId;  // updated by android_atomic_inc | 
| Glenn Kasten | f78aee7 | 2012-01-04 11:00:47 -0800 | [diff] [blame] | 1748 | audio_mode_t                        mMode; | 
| Eric Laurent | bee5337 | 2011-08-29 12:42:48 -0700 | [diff] [blame] | 1749 | bool                                mBtNrecIsOff; | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1750 |  | 
| Glenn Kasten | 99e53b8 | 2012-01-19 08:59:58 -0800 | [diff] [blame] | 1751 | // protected by mLock | 
| Marco Nelissen | 3a34bef | 2011-08-02 13:33:41 -0700 | [diff] [blame] | 1752 | Vector<AudioSessionRef*> mAudioSessionRefs; | 
| Glenn Kasten | 9806710 | 2011-12-13 11:47:54 -0800 | [diff] [blame] | 1753 |  | 
| John Grossman | 4ff14ba | 2012-02-08 16:37:41 -0800 | [diff] [blame] | 1754 | float       masterVolume_l() const; | 
|  | 1755 | float       masterVolumeSW_l() const  { return mMasterVolumeSW; } | 
| Glenn Kasten | 9806710 | 2011-12-13 11:47:54 -0800 | [diff] [blame] | 1756 | bool        masterMute_l() const    { return mMasterMute; } | 
| Glenn Kasten | 98ec94c | 2012-01-25 14:28:29 -0800 | [diff] [blame] | 1757 |  | 
| Eric Laurent | a011e35 | 2012-03-29 15:51:43 -0700 | [diff] [blame] | 1758 | Vector < sp<SyncEvent> > mPendingSyncEvents; // sync events awaiting for a session | 
|  | 1759 | // to be created | 
|  | 1760 |  | 
| Glenn Kasten | 98ec94c | 2012-01-25 14:28:29 -0800 | [diff] [blame] | 1761 | private: | 
|  | 1762 | sp<Client>  registerPid_l(pid_t pid);    // always returns non-0 | 
|  | 1763 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1764 | }; | 
|  | 1765 |  | 
| Dima Zavin | 799a70e | 2011-04-18 16:57:27 -0700 | [diff] [blame] | 1766 |  | 
| Mathias Agopian | 65ab471 | 2010-07-14 17:59:35 -0700 | [diff] [blame] | 1767 | // ---------------------------------------------------------------------------- | 
|  | 1768 |  | 
|  | 1769 | }; // namespace android | 
|  | 1770 |  | 
|  | 1771 | #endif // ANDROID_AUDIO_FLINGER_H |