| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1 | /* | 
|  | 2 | ** | 
|  | 3 | ** Copyright 2012, 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 INCLUDING_FROM_AUDIOFLINGER_H | 
|  | 19 | #error This header file should only be included from AudioFlinger.h | 
|  | 20 | #endif | 
|  | 21 |  | 
|  | 22 | class ThreadBase : public Thread { | 
|  | 23 | public: | 
|  | 24 |  | 
|  | 25 | #include "TrackBase.h" | 
|  | 26 |  | 
|  | 27 | enum type_t { | 
|  | 28 | MIXER,              // Thread class is MixerThread | 
|  | 29 | DIRECT,             // Thread class is DirectOutputThread | 
|  | 30 | DUPLICATING,        // Thread class is DuplicatingThread | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 31 | RECORD,             // Thread class is RecordThread | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 32 | OFFLOAD,            // Thread class is OffloadThread | 
|  | 33 | MMAP                // control thread for MMAP stream | 
| Glenn Kasten | 1bfe09a | 2017-02-21 13:05:56 -0800 | [diff] [blame] | 34 | // If you add any values here, also update ThreadBase::threadTypeToString() | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 35 | }; | 
|  | 36 |  | 
| Glenn Kasten | 97b7b75 | 2014-09-28 13:04:24 -0700 | [diff] [blame] | 37 | static const char *threadTypeToString(type_t type); | 
|  | 38 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 39 | ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id, | 
| Eric Laurent | 72e3f39 | 2015-05-20 14:43:50 -0700 | [diff] [blame] | 40 | audio_devices_t outDevice, audio_devices_t inDevice, type_t type, | 
|  | 41 | bool systemReady); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 42 | virtual             ~ThreadBase(); | 
|  | 43 |  | 
| Glenn Kasten | cf04c2c | 2013-08-06 07:41:16 -0700 | [diff] [blame] | 44 | virtual status_t    readyToRun(); | 
|  | 45 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 46 | void dumpBase(int fd, const Vector<String16>& args); | 
|  | 47 | void dumpEffectChains(int fd, const Vector<String16>& args); | 
|  | 48 |  | 
|  | 49 | void clearPowerManager(); | 
|  | 50 |  | 
|  | 51 | // base for record and playback | 
|  | 52 | enum { | 
|  | 53 | CFG_EVENT_IO, | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 54 | CFG_EVENT_PRIO, | 
|  | 55 | CFG_EVENT_SET_PARAMETER, | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 56 | CFG_EVENT_CREATE_AUDIO_PATCH, | 
|  | 57 | CFG_EVENT_RELEASE_AUDIO_PATCH, | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 58 | }; | 
|  | 59 |  | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 60 | class ConfigEventData: public RefBase { | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 61 | public: | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 62 | virtual ~ConfigEventData() {} | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 63 |  | 
|  | 64 | virtual  void dump(char *buffer, size_t size) = 0; | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 65 | protected: | 
|  | 66 | ConfigEventData() {} | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 67 | }; | 
|  | 68 |  | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 69 | // Config event sequence by client if status needed (e.g binder thread calling setParameters()): | 
|  | 70 | //  1. create SetParameterConfigEvent. This sets mWaitStatus in config event | 
|  | 71 | //  2. Lock mLock | 
|  | 72 | //  3. Call sendConfigEvent_l(): Append to mConfigEvents and mWaitWorkCV.signal | 
|  | 73 | //  4. sendConfigEvent_l() reads status from event->mStatus; | 
|  | 74 | //  5. sendConfigEvent_l() returns status | 
|  | 75 | //  6. Unlock | 
|  | 76 | // | 
|  | 77 | // Parameter sequence by server: threadLoop calling processConfigEvents_l(): | 
|  | 78 | // 1. Lock mLock | 
|  | 79 | // 2. If there is an entry in mConfigEvents proceed ... | 
|  | 80 | // 3. Read first entry in mConfigEvents | 
|  | 81 | // 4. Remove first entry from mConfigEvents | 
|  | 82 | // 5. Process | 
|  | 83 | // 6. Set event->mStatus | 
|  | 84 | // 7. event->mCond.signal | 
|  | 85 | // 8. Unlock | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 86 |  | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 87 | class ConfigEvent: public RefBase { | 
|  | 88 | public: | 
|  | 89 | virtual ~ConfigEvent() {} | 
|  | 90 |  | 
|  | 91 | void dump(char *buffer, size_t size) { mData->dump(buffer, size); } | 
|  | 92 |  | 
|  | 93 | const int mType; // event type e.g. CFG_EVENT_IO | 
|  | 94 | Mutex mLock;     // mutex associated with mCond | 
|  | 95 | Condition mCond; // condition for status return | 
|  | 96 | status_t mStatus; // status communicated to sender | 
|  | 97 | bool mWaitStatus; // true if sender is waiting for status | 
| Eric Laurent | 72e3f39 | 2015-05-20 14:43:50 -0700 | [diff] [blame] | 98 | bool mRequiresSystemReady; // true if must wait for system ready to enter event queue | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 99 | sp<ConfigEventData> mData;     // event specific parameter data | 
|  | 100 |  | 
|  | 101 | protected: | 
| Chih-Hung Hsieh | e964d4e | 2016-08-09 14:31:32 -0700 | [diff] [blame] | 102 | explicit ConfigEvent(int type, bool requiresSystemReady = false) : | 
| Eric Laurent | 72e3f39 | 2015-05-20 14:43:50 -0700 | [diff] [blame] | 103 | mType(type), mStatus(NO_ERROR), mWaitStatus(false), | 
|  | 104 | mRequiresSystemReady(requiresSystemReady), mData(NULL) {} | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 105 | }; | 
|  | 106 |  | 
|  | 107 | class IoConfigEventData : public ConfigEventData { | 
|  | 108 | public: | 
| Eric Laurent | 7c1ec5f | 2015-07-09 14:52:47 -0700 | [diff] [blame] | 109 | IoConfigEventData(audio_io_config_event event, pid_t pid) : | 
|  | 110 | mEvent(event), mPid(pid) {} | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 111 |  | 
|  | 112 | virtual  void dump(char *buffer, size_t size) { | 
| Eric Laurent | 73e26b6 | 2015-04-27 16:55:58 -0700 | [diff] [blame] | 113 | snprintf(buffer, size, "IO event: event %d\n", mEvent); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 114 | } | 
|  | 115 |  | 
| Eric Laurent | 73e26b6 | 2015-04-27 16:55:58 -0700 | [diff] [blame] | 116 | const audio_io_config_event mEvent; | 
| Eric Laurent | 7c1ec5f | 2015-07-09 14:52:47 -0700 | [diff] [blame] | 117 | const pid_t                 mPid; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 118 | }; | 
|  | 119 |  | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 120 | class IoConfigEvent : public ConfigEvent { | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 121 | public: | 
| Eric Laurent | 7c1ec5f | 2015-07-09 14:52:47 -0700 | [diff] [blame] | 122 | IoConfigEvent(audio_io_config_event event, pid_t pid) : | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 123 | ConfigEvent(CFG_EVENT_IO) { | 
| Eric Laurent | 7c1ec5f | 2015-07-09 14:52:47 -0700 | [diff] [blame] | 124 | mData = new IoConfigEventData(event, pid); | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 125 | } | 
|  | 126 | virtual ~IoConfigEvent() {} | 
|  | 127 | }; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 128 |  | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 129 | class PrioConfigEventData : public ConfigEventData { | 
|  | 130 | public: | 
| Mikhail Naganov | 83f0427 | 2017-02-07 10:45:09 -0800 | [diff] [blame] | 131 | PrioConfigEventData(pid_t pid, pid_t tid, int32_t prio, bool forApp) : | 
|  | 132 | mPid(pid), mTid(tid), mPrio(prio), mForApp(forApp) {} | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 133 |  | 
|  | 134 | virtual  void dump(char *buffer, size_t size) { | 
| Mikhail Naganov | 83f0427 | 2017-02-07 10:45:09 -0800 | [diff] [blame] | 135 | snprintf(buffer, size, "Prio event: pid %d, tid %d, prio %d, for app? %d\n", | 
|  | 136 | mPid, mTid, mPrio, mForApp); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 137 | } | 
|  | 138 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 139 | const pid_t mPid; | 
|  | 140 | const pid_t mTid; | 
|  | 141 | const int32_t mPrio; | 
| Mikhail Naganov | 83f0427 | 2017-02-07 10:45:09 -0800 | [diff] [blame] | 142 | const bool mForApp; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 143 | }; | 
|  | 144 |  | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 145 | class PrioConfigEvent : public ConfigEvent { | 
|  | 146 | public: | 
| Mikhail Naganov | 83f0427 | 2017-02-07 10:45:09 -0800 | [diff] [blame] | 147 | PrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp) : | 
| Eric Laurent | 72e3f39 | 2015-05-20 14:43:50 -0700 | [diff] [blame] | 148 | ConfigEvent(CFG_EVENT_PRIO, true) { | 
| Mikhail Naganov | 83f0427 | 2017-02-07 10:45:09 -0800 | [diff] [blame] | 149 | mData = new PrioConfigEventData(pid, tid, prio, forApp); | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 150 | } | 
|  | 151 | virtual ~PrioConfigEvent() {} | 
|  | 152 | }; | 
|  | 153 |  | 
|  | 154 | class SetParameterConfigEventData : public ConfigEventData { | 
|  | 155 | public: | 
| Chih-Hung Hsieh | e964d4e | 2016-08-09 14:31:32 -0700 | [diff] [blame] | 156 | explicit SetParameterConfigEventData(String8 keyValuePairs) : | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 157 | mKeyValuePairs(keyValuePairs) {} | 
|  | 158 |  | 
|  | 159 | virtual  void dump(char *buffer, size_t size) { | 
|  | 160 | snprintf(buffer, size, "KeyValue: %s\n", mKeyValuePairs.string()); | 
|  | 161 | } | 
|  | 162 |  | 
|  | 163 | const String8 mKeyValuePairs; | 
|  | 164 | }; | 
|  | 165 |  | 
|  | 166 | class SetParameterConfigEvent : public ConfigEvent { | 
|  | 167 | public: | 
| Chih-Hung Hsieh | e964d4e | 2016-08-09 14:31:32 -0700 | [diff] [blame] | 168 | explicit SetParameterConfigEvent(String8 keyValuePairs) : | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 169 | ConfigEvent(CFG_EVENT_SET_PARAMETER) { | 
|  | 170 | mData = new SetParameterConfigEventData(keyValuePairs); | 
|  | 171 | mWaitStatus = true; | 
|  | 172 | } | 
|  | 173 | virtual ~SetParameterConfigEvent() {} | 
|  | 174 | }; | 
|  | 175 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 176 | class CreateAudioPatchConfigEventData : public ConfigEventData { | 
|  | 177 | public: | 
|  | 178 | CreateAudioPatchConfigEventData(const struct audio_patch patch, | 
|  | 179 | audio_patch_handle_t handle) : | 
|  | 180 | mPatch(patch), mHandle(handle) {} | 
|  | 181 |  | 
|  | 182 | virtual  void dump(char *buffer, size_t size) { | 
|  | 183 | snprintf(buffer, size, "Patch handle: %u\n", mHandle); | 
|  | 184 | } | 
|  | 185 |  | 
|  | 186 | const struct audio_patch mPatch; | 
|  | 187 | audio_patch_handle_t mHandle; | 
|  | 188 | }; | 
|  | 189 |  | 
|  | 190 | class CreateAudioPatchConfigEvent : public ConfigEvent { | 
|  | 191 | public: | 
|  | 192 | CreateAudioPatchConfigEvent(const struct audio_patch patch, | 
|  | 193 | audio_patch_handle_t handle) : | 
|  | 194 | ConfigEvent(CFG_EVENT_CREATE_AUDIO_PATCH) { | 
|  | 195 | mData = new CreateAudioPatchConfigEventData(patch, handle); | 
|  | 196 | mWaitStatus = true; | 
|  | 197 | } | 
|  | 198 | virtual ~CreateAudioPatchConfigEvent() {} | 
|  | 199 | }; | 
|  | 200 |  | 
|  | 201 | class ReleaseAudioPatchConfigEventData : public ConfigEventData { | 
|  | 202 | public: | 
| Chih-Hung Hsieh | e964d4e | 2016-08-09 14:31:32 -0700 | [diff] [blame] | 203 | explicit ReleaseAudioPatchConfigEventData(const audio_patch_handle_t handle) : | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 204 | mHandle(handle) {} | 
|  | 205 |  | 
|  | 206 | virtual  void dump(char *buffer, size_t size) { | 
|  | 207 | snprintf(buffer, size, "Patch handle: %u\n", mHandle); | 
|  | 208 | } | 
|  | 209 |  | 
|  | 210 | audio_patch_handle_t mHandle; | 
|  | 211 | }; | 
|  | 212 |  | 
|  | 213 | class ReleaseAudioPatchConfigEvent : public ConfigEvent { | 
|  | 214 | public: | 
| Chih-Hung Hsieh | e964d4e | 2016-08-09 14:31:32 -0700 | [diff] [blame] | 215 | explicit ReleaseAudioPatchConfigEvent(const audio_patch_handle_t handle) : | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 216 | ConfigEvent(CFG_EVENT_RELEASE_AUDIO_PATCH) { | 
|  | 217 | mData = new ReleaseAudioPatchConfigEventData(handle); | 
|  | 218 | mWaitStatus = true; | 
|  | 219 | } | 
|  | 220 | virtual ~ReleaseAudioPatchConfigEvent() {} | 
|  | 221 | }; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 222 |  | 
|  | 223 | class PMDeathRecipient : public IBinder::DeathRecipient { | 
|  | 224 | public: | 
| Chih-Hung Hsieh | e964d4e | 2016-08-09 14:31:32 -0700 | [diff] [blame] | 225 | explicit    PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {} | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 226 | virtual     ~PMDeathRecipient() {} | 
|  | 227 |  | 
|  | 228 | // IBinder::DeathRecipient | 
|  | 229 | virtual     void        binderDied(const wp<IBinder>& who); | 
|  | 230 |  | 
|  | 231 | private: | 
| Mikhail Naganov | bf49308 | 2017-04-17 17:37:12 -0700 | [diff] [blame] | 232 | DISALLOW_COPY_AND_ASSIGN(PMDeathRecipient); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 233 |  | 
|  | 234 | wp<ThreadBase> mThread; | 
|  | 235 | }; | 
|  | 236 |  | 
|  | 237 | virtual     status_t    initCheck() const = 0; | 
|  | 238 |  | 
|  | 239 | // static externally-visible | 
|  | 240 | type_t      type() const { return mType; } | 
| Eric Laurent | f6870ae | 2015-05-08 10:50:03 -0700 | [diff] [blame] | 241 | bool isDuplicating() const { return (mType == DUPLICATING); } | 
|  | 242 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 243 | audio_io_handle_t id() const { return mId;} | 
|  | 244 |  | 
|  | 245 | // dynamic externally-visible | 
|  | 246 | uint32_t    sampleRate() const { return mSampleRate; } | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 247 | audio_channel_mask_t channelMask() const { return mChannelMask; } | 
| Andy Hung | 463be25 | 2014-07-10 16:56:07 -0700 | [diff] [blame] | 248 | audio_format_t format() const { return mHALFormat; } | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 249 | uint32_t channelCount() const { return mChannelCount; } | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 250 | // Called by AudioFlinger::frameCount(audio_io_handle_t output) and effects, | 
| Glenn Kasten | 9b58f63 | 2013-07-16 11:37:48 -0700 | [diff] [blame] | 251 | // and returns the [normal mix] buffer's frame count. | 
|  | 252 | virtual     size_t      frameCount() const = 0; | 
| Glenn Kasten | 4a8308b | 2016-04-18 14:10:01 -0700 | [diff] [blame] | 253 |  | 
|  | 254 | // Return's the HAL's frame count i.e. fast mixer buffer size. | 
|  | 255 | size_t      frameCountHAL() const { return mFrameCount; } | 
|  | 256 |  | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 257 | size_t      frameSize() const { return mFrameSize; } | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 258 |  | 
|  | 259 | // Should be "virtual status_t requestExitAndWait()" and override same | 
|  | 260 | // method in Thread, but Thread::requestExitAndWait() is not yet virtual. | 
|  | 261 | void        exit(); | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 262 | virtual     bool        checkForNewParameter_l(const String8& keyValuePair, | 
|  | 263 | status_t& status) = 0; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 264 | virtual     status_t    setParameters(const String8& keyValuePairs); | 
|  | 265 | virtual     String8     getParameters(const String8& keys) = 0; | 
| Eric Laurent | 7c1ec5f | 2015-07-09 14:52:47 -0700 | [diff] [blame] | 266 | virtual     void        ioConfigChanged(audio_io_config_event event, pid_t pid = 0) = 0; | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 267 | // sendConfigEvent_l() must be called with ThreadBase::mLock held | 
|  | 268 | // Can temporarily release the lock if waiting for a reply from | 
|  | 269 | // processConfigEvents_l(). | 
|  | 270 | status_t    sendConfigEvent_l(sp<ConfigEvent>& event); | 
| Eric Laurent | 7c1ec5f | 2015-07-09 14:52:47 -0700 | [diff] [blame] | 271 | void        sendIoConfigEvent(audio_io_config_event event, pid_t pid = 0); | 
|  | 272 | void        sendIoConfigEvent_l(audio_io_config_event event, pid_t pid = 0); | 
| Mikhail Naganov | 83f0427 | 2017-02-07 10:45:09 -0800 | [diff] [blame] | 273 | void        sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp); | 
|  | 274 | void        sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp); | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 275 | status_t    sendSetParameterConfigEvent_l(const String8& keyValuePair); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 276 | status_t    sendCreateAudioPatchConfigEvent(const struct audio_patch *patch, | 
|  | 277 | audio_patch_handle_t *handle); | 
|  | 278 | status_t    sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle); | 
| Eric Laurent | 021cf96 | 2014-05-13 10:18:14 -0700 | [diff] [blame] | 279 | void        processConfigEvents_l(); | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 280 | virtual     void        cacheParameters_l() = 0; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 281 | virtual     status_t    createAudioPatch_l(const struct audio_patch *patch, | 
|  | 282 | audio_patch_handle_t *handle) = 0; | 
|  | 283 | virtual     status_t    releaseAudioPatch_l(const audio_patch_handle_t handle) = 0; | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 284 | virtual     void        getAudioPortConfig(struct audio_port_config *config) = 0; | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 285 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 286 |  | 
|  | 287 | // see note at declaration of mStandby, mOutDevice and mInDevice | 
|  | 288 | bool        standby() const { return mStandby; } | 
|  | 289 | audio_devices_t outDevice() const { return mOutDevice; } | 
|  | 290 | audio_devices_t inDevice() const { return mInDevice; } | 
| Andy Hung | 293558a | 2017-03-21 12:19:20 -0700 | [diff] [blame] | 291 | audio_devices_t getDevice() const { return isOutput() ? mOutDevice : mInDevice; } | 
|  | 292 |  | 
|  | 293 | virtual     bool        isOutput() const = 0; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 294 |  | 
| Mikhail Naganov | 1dc9867 | 2016-08-18 17:50:29 -0700 | [diff] [blame] | 295 | virtual     sp<StreamHalInterface> stream() const = 0; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 296 |  | 
|  | 297 | sp<EffectHandle> createEffect_l( | 
|  | 298 | const sp<AudioFlinger::Client>& client, | 
|  | 299 | const sp<IEffectClient>& effectClient, | 
|  | 300 | int32_t priority, | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 301 | audio_session_t sessionId, | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 302 | effect_descriptor_t *desc, | 
|  | 303 | int *enabled, | 
| Eric Laurent | 0d5a2ed | 2016-12-01 15:28:29 -0800 | [diff] [blame] | 304 | status_t *status /*non-NULL*/, | 
|  | 305 | bool pinned); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 306 |  | 
|  | 307 | // return values for hasAudioSession (bit field) | 
|  | 308 | enum effect_state { | 
|  | 309 | EFFECT_SESSION = 0x1,   // the audio session corresponds to at least one | 
|  | 310 | // effect | 
| Eric Laurent | 4c41506 | 2016-06-17 16:14:16 -0700 | [diff] [blame] | 311 | TRACK_SESSION = 0x2,    // the audio session corresponds to at least one | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 312 | // track | 
| Eric Laurent | 4c41506 | 2016-06-17 16:14:16 -0700 | [diff] [blame] | 313 | FAST_SESSION = 0x4      // the audio session corresponds to at least one | 
|  | 314 | // fast track | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 315 | }; | 
|  | 316 |  | 
|  | 317 | // get effect chain corresponding to session Id. | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 318 | sp<EffectChain> getEffectChain(audio_session_t sessionId); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 319 | // same as getEffectChain() but must be called with ThreadBase mutex locked | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 320 | sp<EffectChain> getEffectChain_l(audio_session_t sessionId) const; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 321 | // add an effect chain to the chain list (mEffectChains) | 
|  | 322 | virtual     status_t addEffectChain_l(const sp<EffectChain>& chain) = 0; | 
|  | 323 | // remove an effect chain from the chain list (mEffectChains) | 
|  | 324 | virtual     size_t removeEffectChain_l(const sp<EffectChain>& chain) = 0; | 
|  | 325 | // lock all effect chains Mutexes. Must be called before releasing the | 
|  | 326 | // ThreadBase mutex before processing the mixer and effects. This guarantees the | 
|  | 327 | // integrity of the chains during the process. | 
|  | 328 | // Also sets the parameter 'effectChains' to current value of mEffectChains. | 
|  | 329 | void lockEffectChains_l(Vector< sp<EffectChain> >& effectChains); | 
|  | 330 | // unlock effect chains after process | 
|  | 331 | void unlockEffectChains(const Vector< sp<EffectChain> >& effectChains); | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 332 | // get a copy of mEffectChains vector | 
|  | 333 | Vector< sp<EffectChain> > getEffectChains_l() const { return mEffectChains; }; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 334 | // set audio mode to all effect chains | 
|  | 335 | void setMode(audio_mode_t mode); | 
|  | 336 | // get effect module with corresponding ID on specified audio session | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 337 | sp<AudioFlinger::EffectModule> getEffect(audio_session_t sessionId, int effectId); | 
|  | 338 | sp<AudioFlinger::EffectModule> getEffect_l(audio_session_t sessionId, int effectId); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 339 | // add and effect module. Also creates the effect chain is none exists for | 
|  | 340 | // the effects audio session | 
|  | 341 | status_t addEffect_l(const sp< EffectModule>& effect); | 
|  | 342 | // remove and effect module. Also removes the effect chain is this was the last | 
|  | 343 | // effect | 
| Eric Laurent | 0d5a2ed | 2016-12-01 15:28:29 -0800 | [diff] [blame] | 344 | void removeEffect_l(const sp< EffectModule>& effect, bool release = false); | 
|  | 345 | // disconnect an effect handle from module and destroy module if last handle | 
|  | 346 | void disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 347 | // detach all tracks connected to an auxiliary effect | 
| Glenn Kasten | 0f11b51 | 2014-01-31 16:18:54 -0800 | [diff] [blame] | 348 | virtual     void detachAuxEffect_l(int effectId __unused) {} | 
| Eric Laurent | 4c41506 | 2016-06-17 16:14:16 -0700 | [diff] [blame] | 349 | // returns a combination of: | 
|  | 350 | // - EFFECT_SESSION if effects on this audio session exist in one chain | 
|  | 351 | // - TRACK_SESSION if tracks on this audio session exist | 
|  | 352 | // - FAST_SESSION if fast tracks on this audio session exist | 
|  | 353 | virtual     uint32_t hasAudioSession_l(audio_session_t sessionId) const = 0; | 
|  | 354 | uint32_t hasAudioSession(audio_session_t sessionId) const { | 
|  | 355 | Mutex::Autolock _l(mLock); | 
|  | 356 | return hasAudioSession_l(sessionId); | 
|  | 357 | } | 
|  | 358 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 359 | // the value returned by default implementation is not important as the | 
|  | 360 | // strategy is only meaningful for PlaybackThread which implements this method | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 361 | virtual uint32_t getStrategyForSession_l(audio_session_t sessionId __unused) | 
|  | 362 | { return 0; } | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 363 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 364 | // check if some effects must be suspended/restored when an effect is enabled | 
|  | 365 | // or disabled | 
|  | 366 | void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect, | 
|  | 367 | bool enabled, | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 368 | audio_session_t sessionId = | 
|  | 369 | AUDIO_SESSION_OUTPUT_MIX); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 370 | void checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect, | 
|  | 371 | bool enabled, | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 372 | audio_session_t sessionId = | 
|  | 373 | AUDIO_SESSION_OUTPUT_MIX); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 374 |  | 
|  | 375 | virtual status_t    setSyncEvent(const sp<SyncEvent>& event) = 0; | 
|  | 376 | virtual bool        isValidSyncEvent(const sp<SyncEvent>& event) const = 0; | 
|  | 377 |  | 
| Glenn Kasten | b880f5e | 2014-05-07 08:43:45 -0700 | [diff] [blame] | 378 | // Return a reference to a per-thread heap which can be used to allocate IMemory | 
|  | 379 | // objects that will be read-only to client processes, read/write to mediaserver, | 
|  | 380 | // and shared by all client processes of the thread. | 
|  | 381 | // The heap is per-thread rather than common across all threads, because | 
|  | 382 | // clients can't be trusted not to modify the offset of the IMemory they receive. | 
|  | 383 | // If a thread does not have such a heap, this method returns 0. | 
|  | 384 | virtual sp<MemoryDealer>    readOnlyHeap() const { return 0; } | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 385 |  | 
| Glenn Kasten | 6181ffd | 2014-05-13 10:41:52 -0700 | [diff] [blame] | 386 | virtual sp<IMemory> pipeMemory() const { return 0; } | 
|  | 387 |  | 
| Eric Laurent | 72e3f39 | 2015-05-20 14:43:50 -0700 | [diff] [blame] | 388 | void systemReady(); | 
|  | 389 |  | 
| Eric Laurent | 4c41506 | 2016-06-17 16:14:16 -0700 | [diff] [blame] | 390 | // checkEffectCompatibility_l() must be called with ThreadBase::mLock held | 
|  | 391 | virtual status_t    checkEffectCompatibility_l(const effect_descriptor_t *desc, | 
|  | 392 | audio_session_t sessionId) = 0; | 
|  | 393 |  | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 394 | void        broadcast_l(); | 
|  | 395 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 396 | mutable     Mutex                   mLock; | 
|  | 397 |  | 
|  | 398 | protected: | 
|  | 399 |  | 
|  | 400 | // entry describing an effect being suspended in mSuspendedSessions keyed vector | 
|  | 401 | class SuspendedSessionDesc : public RefBase { | 
|  | 402 | public: | 
|  | 403 | SuspendedSessionDesc() : mRefCount(0) {} | 
|  | 404 |  | 
|  | 405 | int mRefCount;          // number of active suspend requests | 
|  | 406 | effect_uuid_t mType;    // effect type UUID | 
|  | 407 | }; | 
|  | 408 |  | 
| Andy Hung | dae2770 | 2016-10-31 14:01:16 -0700 | [diff] [blame] | 409 | void        acquireWakeLock(); | 
|  | 410 | virtual void acquireWakeLock_l(); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 411 | void        releaseWakeLock(); | 
|  | 412 | void        releaseWakeLock_l(); | 
| Andy Hung | d01b0f1 | 2016-11-07 16:10:30 -0800 | [diff] [blame] | 413 | void        updateWakeLockUids_l(const SortedVector<uid_t> &uids); | 
| Marco Nelissen | 462fd2f | 2013-01-14 14:12:05 -0800 | [diff] [blame] | 414 | void        getPowerManager_l(); | 
| Eric Laurent | d8365c5 | 2017-07-16 15:27:05 -0700 | [diff] [blame] | 415 | // suspend or restore effects of the specified type (or all if type is NULL) | 
|  | 416 | // on a given session. The number of suspend requests is counted and restore | 
|  | 417 | // occurs when all suspend requests are cancelled. | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 418 | void setEffectSuspended_l(const effect_uuid_t *type, | 
|  | 419 | bool suspend, | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 420 | audio_session_t sessionId); | 
| Eric Laurent | d8365c5 | 2017-07-16 15:27:05 -0700 | [diff] [blame] | 421 | // updated mSuspendedSessions when an effect is suspended or restored | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 422 | void        updateSuspendedSessions_l(const effect_uuid_t *type, | 
|  | 423 | bool suspend, | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 424 | audio_session_t sessionId); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 425 | // check if some effects must be suspended when an effect chain is added | 
|  | 426 | void checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain); | 
|  | 427 |  | 
| Kevin Rocard | 069c271 | 2018-03-29 19:09:14 -0700 | [diff] [blame] | 428 | // sends the metadata of the active tracks to the HAL | 
|  | 429 | virtual     void        updateMetadata_l() = 0; | 
|  | 430 |  | 
| Narayan Kamath | 014e7fa | 2013-10-14 15:03:38 +0100 | [diff] [blame] | 431 | String16 getWakeLockTag(); | 
|  | 432 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 433 | virtual     void        preExit() { } | 
| Andy Hung | 2ddee19 | 2015-12-18 17:34:44 -0800 | [diff] [blame] | 434 | virtual     void        setMasterMono_l(bool mono __unused) { } | 
|  | 435 | virtual     bool        requireMonoBlend() { return false; } | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 436 |  | 
|  | 437 | friend class AudioFlinger;      // for mEffectChains | 
|  | 438 |  | 
|  | 439 | const type_t            mType; | 
|  | 440 |  | 
|  | 441 | // Used by parameters, config events, addTrack_l, exit | 
|  | 442 | Condition               mWaitWorkCV; | 
|  | 443 |  | 
|  | 444 | const sp<AudioFlinger>  mAudioFlinger; | 
| Glenn Kasten | 9b58f63 | 2013-07-16 11:37:48 -0700 | [diff] [blame] | 445 |  | 
| Glenn Kasten | deca2ae | 2014-02-07 10:25:56 -0800 | [diff] [blame] | 446 | // updated by PlaybackThread::readOutputParameters_l() or | 
|  | 447 | // RecordThread::readInputParameters_l() | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 448 | uint32_t                mSampleRate; | 
|  | 449 | size_t                  mFrameCount;       // output HAL, direct output, record | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 450 | audio_channel_mask_t    mChannelMask; | 
| Glenn Kasten | f6ed423 | 2013-07-16 11:16:27 -0700 | [diff] [blame] | 451 | uint32_t                mChannelCount; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 452 | size_t                  mFrameSize; | 
| Glenn Kasten | 97b7b75 | 2014-09-28 13:04:24 -0700 | [diff] [blame] | 453 | // not HAL frame size, this is for output sink (to pipe to fast mixer) | 
| Andy Hung | 463be25 | 2014-07-10 16:56:07 -0700 | [diff] [blame] | 454 | audio_format_t          mFormat;           // Source format for Recording and | 
|  | 455 | // Sink format for Playback. | 
|  | 456 | // Sink format may be different than | 
|  | 457 | // HAL format if Fastmixer is used. | 
|  | 458 | audio_format_t          mHALFormat; | 
| Glenn Kasten | 70949c4 | 2013-08-06 07:40:12 -0700 | [diff] [blame] | 459 | size_t                  mBufferSize;       // HAL buffer size for read() or write() | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 460 |  | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 461 | Vector< sp<ConfigEvent> >     mConfigEvents; | 
| Eric Laurent | 72e3f39 | 2015-05-20 14:43:50 -0700 | [diff] [blame] | 462 | Vector< sp<ConfigEvent> >     mPendingConfigEvents; // events awaiting system ready | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 463 |  | 
|  | 464 | // These fields are written and read by thread itself without lock or barrier, | 
| Glenn Kasten | 4944acb | 2013-08-19 08:39:20 -0700 | [diff] [blame] | 465 | // and read by other threads without lock or barrier via standby(), outDevice() | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 466 | // and inDevice(). | 
|  | 467 | // Because of the absence of a lock or barrier, any other thread that reads | 
|  | 468 | // these fields must use the information in isolation, or be prepared to deal | 
|  | 469 | // with possibility that it might be inconsistent with other information. | 
| Glenn Kasten | 4944acb | 2013-08-19 08:39:20 -0700 | [diff] [blame] | 470 | bool                    mStandby;     // Whether thread is currently in standby. | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 471 | audio_devices_t         mOutDevice;   // output device | 
|  | 472 | audio_devices_t         mInDevice;    // input device | 
| Eric Laurent | 7c1ec5f | 2015-07-09 14:52:47 -0700 | [diff] [blame] | 473 | audio_devices_t         mPrevOutDevice;   // previous output device | 
| Eric Laurent | e8726fe | 2015-06-26 09:39:24 -0700 | [diff] [blame] | 474 | audio_devices_t         mPrevInDevice;    // previous input device | 
| Eric Laurent | 296fb13 | 2015-05-01 11:38:42 -0700 | [diff] [blame] | 475 | struct audio_patch      mPatch; | 
| Glenn Kasten | f59497b | 2015-01-26 16:35:47 -0800 | [diff] [blame] | 476 | audio_source_t          mAudioSource; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 477 |  | 
|  | 478 | const audio_io_handle_t mId; | 
|  | 479 | Vector< sp<EffectChain> > mEffectChains; | 
|  | 480 |  | 
| Glenn Kasten | d7dca05 | 2015-03-05 16:05:54 -0800 | [diff] [blame] | 481 | static const int        kThreadNameLength = 16; // prctl(PR_SET_NAME) limit | 
|  | 482 | char                    mThreadName[kThreadNameLength]; // guaranteed NUL-terminated | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 483 | sp<IPowerManager>       mPowerManager; | 
|  | 484 | sp<IBinder>             mWakeLockToken; | 
|  | 485 | const sp<PMDeathRecipient> mDeathRecipient; | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 486 | // list of suspended effects per session and per type. The first (outer) vector is | 
|  | 487 | // keyed by session ID, the second (inner) by type UUID timeLow field | 
| Eric Laurent | d8365c5 | 2017-07-16 15:27:05 -0700 | [diff] [blame] | 488 | // Updated by updateSuspendedSessions_l() only. | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 489 | KeyedVector< audio_session_t, KeyedVector< int, sp<SuspendedSessionDesc> > > | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 490 | mSuspendedSessions; | 
| Sanna Catherine de Treville Wager | 2a6a945 | 2017-07-28 11:02:01 -0700 | [diff] [blame] | 491 | // TODO: add comment and adjust size as needed | 
| Glenn Kasten | ab7d72f | 2013-02-27 09:05:28 -0800 | [diff] [blame] | 492 | static const size_t     kLogSize = 4 * 1024; | 
| Glenn Kasten | 9e58b55 | 2013-01-18 15:09:48 -0800 | [diff] [blame] | 493 | sp<NBLog::Writer>       mNBLogWriter; | 
| Eric Laurent | 72e3f39 | 2015-05-20 14:43:50 -0700 | [diff] [blame] | 494 | bool                    mSystemReady; | 
| Andy Hung | 818e7a3 | 2016-02-16 18:08:07 -0800 | [diff] [blame] | 495 | ExtendedTimestamp       mTimestamp; | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 496 | // A condition that must be evaluated by the thread loop has changed and | 
|  | 497 | // we must not wait for async write callback in the thread loop before evaluating it | 
|  | 498 | bool                    mSignalPending; | 
| Andy Hung | dae2770 | 2016-10-31 14:01:16 -0700 | [diff] [blame] | 499 |  | 
|  | 500 | // ActiveTracks is a sorted vector of track type T representing the | 
|  | 501 | // active tracks of threadLoop() to be considered by the locked prepare portion. | 
|  | 502 | // ActiveTracks should be accessed with the ThreadBase lock held. | 
|  | 503 | // | 
|  | 504 | // During processing and I/O, the threadLoop does not hold the lock; | 
|  | 505 | // hence it does not directly use ActiveTracks.  Care should be taken | 
|  | 506 | // to hold local strong references or defer removal of tracks | 
|  | 507 | // if the threadLoop may still be accessing those tracks due to mix, etc. | 
|  | 508 | // | 
|  | 509 | // This class updates power information appropriately. | 
|  | 510 | // | 
|  | 511 |  | 
|  | 512 | template <typename T> | 
|  | 513 | class ActiveTracks { | 
|  | 514 | public: | 
| Andy Hung | 2c6c3bb | 2017-06-16 14:01:45 -0700 | [diff] [blame] | 515 | explicit ActiveTracks(SimpleLog *localLog = nullptr) | 
| Andy Hung | dae2770 | 2016-10-31 14:01:16 -0700 | [diff] [blame] | 516 | : mActiveTracksGeneration(0) | 
|  | 517 | , mLastActiveTracksGeneration(0) | 
| Andy Hung | 2c6c3bb | 2017-06-16 14:01:45 -0700 | [diff] [blame] | 518 | , mLocalLog(localLog) | 
| Andy Hung | dae2770 | 2016-10-31 14:01:16 -0700 | [diff] [blame] | 519 | { } | 
|  | 520 |  | 
|  | 521 | ~ActiveTracks() { | 
|  | 522 | ALOGW_IF(!mActiveTracks.isEmpty(), | 
|  | 523 | "ActiveTracks should be empty in destructor"); | 
|  | 524 | } | 
|  | 525 | // returns the last track added (even though it may have been | 
|  | 526 | // subsequently removed from ActiveTracks). | 
|  | 527 | // | 
|  | 528 | // Used for DirectOutputThread to ensure a flush is called when transitioning | 
|  | 529 | // to a new track (even though it may be on the same session). | 
|  | 530 | // Used for OffloadThread to ensure that volume and mixer state is | 
|  | 531 | // taken from the latest track added. | 
|  | 532 | // | 
|  | 533 | // The latest track is saved with a weak pointer to prevent keeping an | 
|  | 534 | // otherwise useless track alive. Thus the function will return nullptr | 
|  | 535 | // if the latest track has subsequently been removed and destroyed. | 
|  | 536 | sp<T> getLatest() { | 
|  | 537 | return mLatestActiveTrack.promote(); | 
|  | 538 | } | 
|  | 539 |  | 
|  | 540 | // SortedVector methods | 
|  | 541 | ssize_t         add(const sp<T> &track); | 
|  | 542 | ssize_t         remove(const sp<T> &track); | 
|  | 543 | size_t          size() const { | 
|  | 544 | return mActiveTracks.size(); | 
|  | 545 | } | 
|  | 546 | ssize_t         indexOf(const sp<T>& item) { | 
|  | 547 | return mActiveTracks.indexOf(item); | 
|  | 548 | } | 
|  | 549 | sp<T>           operator[](size_t index) const { | 
|  | 550 | return mActiveTracks[index]; | 
|  | 551 | } | 
|  | 552 | typename SortedVector<sp<T>>::iterator begin() { | 
|  | 553 | return mActiveTracks.begin(); | 
|  | 554 | } | 
|  | 555 | typename SortedVector<sp<T>>::iterator end() { | 
|  | 556 | return mActiveTracks.end(); | 
|  | 557 | } | 
|  | 558 |  | 
|  | 559 | // Due to Binder recursion optimization, clear() and updatePowerState() | 
|  | 560 | // cannot be called from a Binder thread because they may call back into | 
|  | 561 | // the original calling process (system server) for BatteryNotifier | 
|  | 562 | // (which requires a Java environment that may not be present). | 
|  | 563 | // Hence, call clear() and updatePowerState() only from the | 
|  | 564 | // ThreadBase thread. | 
|  | 565 | void            clear(); | 
|  | 566 | // periodically called in the threadLoop() to update power state uids. | 
|  | 567 | void            updatePowerState(sp<ThreadBase> thread, bool force = false); | 
|  | 568 |  | 
| Kevin Rocard | c86a7f7 | 2018-04-03 09:00:09 -0700 | [diff] [blame] | 569 | /** @return true if one or move active tracks was added or removed since the | 
|  | 570 | *          last time this function was called or the vector was created. */ | 
| Kevin Rocard | 069c271 | 2018-03-29 19:09:14 -0700 | [diff] [blame] | 571 | bool            readAndClearHasChanged(); | 
|  | 572 |  | 
| Andy Hung | dae2770 | 2016-10-31 14:01:16 -0700 | [diff] [blame] | 573 | private: | 
| Andy Hung | 2c6c3bb | 2017-06-16 14:01:45 -0700 | [diff] [blame] | 574 | void            logTrack(const char *funcName, const sp<T> &track) const; | 
|  | 575 |  | 
| Andy Hung | d01b0f1 | 2016-11-07 16:10:30 -0800 | [diff] [blame] | 576 | SortedVector<uid_t> getWakeLockUids() { | 
|  | 577 | SortedVector<uid_t> wakeLockUids; | 
| Andy Hung | dae2770 | 2016-10-31 14:01:16 -0700 | [diff] [blame] | 578 | for (const sp<T> &track : mActiveTracks) { | 
|  | 579 | wakeLockUids.add(track->uid()); | 
|  | 580 | } | 
|  | 581 | return wakeLockUids; // moved by underlying SharedBuffer | 
|  | 582 | } | 
|  | 583 |  | 
|  | 584 | std::map<uid_t, std::pair<ssize_t /* previous */, ssize_t /* current */>> | 
|  | 585 | mBatteryCounter; | 
|  | 586 | SortedVector<sp<T>> mActiveTracks; | 
|  | 587 | int                 mActiveTracksGeneration; | 
|  | 588 | int                 mLastActiveTracksGeneration; | 
|  | 589 | wp<T>               mLatestActiveTrack; // latest track added to ActiveTracks | 
| Andy Hung | 2c6c3bb | 2017-06-16 14:01:45 -0700 | [diff] [blame] | 590 | SimpleLog * const   mLocalLog; | 
| Kevin Rocard | c86a7f7 | 2018-04-03 09:00:09 -0700 | [diff] [blame] | 591 | // If the vector has changed since last call to readAndClearHasChanged | 
| Kevin Rocard | 069c271 | 2018-03-29 19:09:14 -0700 | [diff] [blame] | 592 | bool                mHasChanged = false; | 
| Andy Hung | dae2770 | 2016-10-31 14:01:16 -0700 | [diff] [blame] | 593 | }; | 
| Andy Hung | 293558a | 2017-03-21 12:19:20 -0700 | [diff] [blame] | 594 |  | 
|  | 595 | SimpleLog mLocalLog; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 596 | }; | 
|  | 597 |  | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 598 | class VolumeInterface { | 
|  | 599 | public: | 
|  | 600 |  | 
|  | 601 | virtual ~VolumeInterface() {} | 
|  | 602 |  | 
|  | 603 | virtual void        setMasterVolume(float value) = 0; | 
|  | 604 | virtual void        setMasterMute(bool muted) = 0; | 
|  | 605 | virtual void        setStreamVolume(audio_stream_type_t stream, float value) = 0; | 
|  | 606 | virtual void        setStreamMute(audio_stream_type_t stream, bool muted) = 0; | 
|  | 607 | virtual float       streamVolume(audio_stream_type_t stream) const = 0; | 
|  | 608 |  | 
|  | 609 | }; | 
|  | 610 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 611 | // --- PlaybackThread --- | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 612 | class PlaybackThread : public ThreadBase, public StreamOutHalInterfaceCallback, | 
|  | 613 | public VolumeInterface { | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 614 | public: | 
|  | 615 |  | 
|  | 616 | #include "PlaybackTracks.h" | 
|  | 617 |  | 
|  | 618 | enum mixer_state { | 
|  | 619 | MIXER_IDLE,             // no active tracks | 
|  | 620 | MIXER_TRACKS_ENABLED,   // at least one active track, but no track has any data ready | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 621 | MIXER_TRACKS_READY,      // at least one active track, and at least one track has data | 
|  | 622 | MIXER_DRAIN_TRACK,      // drain currently playing track | 
|  | 623 | MIXER_DRAIN_ALL,        // fully drain the hardware | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 624 | // standby mode does not have an enum value | 
|  | 625 | // suspend by audio policy manager is orthogonal to mixer state | 
|  | 626 | }; | 
|  | 627 |  | 
| Eric Laurent | e93cc03 | 2016-05-05 10:15:10 -0700 | [diff] [blame] | 628 | // retry count before removing active track in case of underrun on offloaded thread: | 
|  | 629 | // we need to make sure that AudioTrack client has enough time to send large buffers | 
|  | 630 | //FIXME may be more appropriate if expressed in time units. Need to revise how underrun is | 
|  | 631 | // handled for offloaded tracks | 
|  | 632 | static const int8_t kMaxTrackRetriesOffload = 20; | 
|  | 633 | static const int8_t kMaxTrackStartupRetriesOffload = 100; | 
|  | 634 | static const int8_t kMaxTrackStopRetriesOffload = 2; | 
| Andy Hung | 8ed196a | 2018-01-05 13:21:11 -0800 | [diff] [blame] | 635 | static constexpr uint32_t kMaxTracksPerUid = 40; | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 636 | static constexpr size_t kMaxTracks = 256; | 
| Eric Laurent | e93cc03 | 2016-05-05 10:15:10 -0700 | [diff] [blame] | 637 |  | 
| rago | 1bb9082 | 2017-05-02 18:31:48 -0700 | [diff] [blame] | 638 | // Maximum delay (in nanoseconds) for upcoming buffers in suspend mode, otherwise | 
|  | 639 | // if delay is greater, the estimated time for timeLoopNextNs is reset. | 
|  | 640 | // This allows for catch-up to be done for small delays, while resetting the estimate | 
|  | 641 | // for initial conditions or large delays. | 
|  | 642 | static const nsecs_t kMaxNextBufferDelayNs = 100000000; | 
|  | 643 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 644 | PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, | 
| Eric Laurent | e93cc03 | 2016-05-05 10:15:10 -0700 | [diff] [blame] | 645 | audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 646 | virtual             ~PlaybackThread(); | 
|  | 647 |  | 
|  | 648 | void        dump(int fd, const Vector<String16>& args); | 
|  | 649 |  | 
|  | 650 | // Thread virtuals | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 651 | virtual     bool        threadLoop(); | 
|  | 652 |  | 
|  | 653 | // RefBase | 
|  | 654 | virtual     void        onFirstRef(); | 
|  | 655 |  | 
| Eric Laurent | 4c41506 | 2016-06-17 16:14:16 -0700 | [diff] [blame] | 656 | virtual     status_t    checkEffectCompatibility_l(const effect_descriptor_t *desc, | 
|  | 657 | audio_session_t sessionId); | 
|  | 658 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 659 | protected: | 
|  | 660 | // Code snippets that were lifted up out of threadLoop() | 
|  | 661 | virtual     void        threadLoop_mix() = 0; | 
|  | 662 | virtual     void        threadLoop_sleepTime() = 0; | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 663 | virtual     ssize_t     threadLoop_write(); | 
|  | 664 | virtual     void        threadLoop_drain(); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 665 | virtual     void        threadLoop_standby(); | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 666 | virtual     void        threadLoop_exit(); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 667 | virtual     void        threadLoop_removeTracks(const Vector< sp<Track> >& tracksToRemove); | 
|  | 668 |  | 
|  | 669 | // prepareTracks_l reads and writes mActiveTracks, and returns | 
|  | 670 | // the pending set of tracks to remove via Vector 'tracksToRemove'.  The caller | 
|  | 671 | // is responsible for clearing or destroying this Vector later on, when it | 
|  | 672 | // is safe to do so. That will drop the final ref count and destroy the tracks. | 
|  | 673 | virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove) = 0; | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 674 | void        removeTracks_l(const Vector< sp<Track> >& tracksToRemove); | 
|  | 675 |  | 
| Mikhail Naganov | 1dc9867 | 2016-08-18 17:50:29 -0700 | [diff] [blame] | 676 | // StreamOutHalInterfaceCallback implementation | 
|  | 677 | virtual     void        onWriteReady(); | 
|  | 678 | virtual     void        onDrainReady(); | 
|  | 679 | virtual     void        onError(); | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 680 |  | 
| Mikhail Naganov | 1dc9867 | 2016-08-18 17:50:29 -0700 | [diff] [blame] | 681 | void        resetWriteBlocked(uint32_t sequence); | 
|  | 682 | void        resetDraining(uint32_t sequence); | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 683 |  | 
|  | 684 | virtual     bool        waitingAsyncCallback(); | 
|  | 685 | virtual     bool        waitingAsyncCallback_l(); | 
|  | 686 | virtual     bool        shouldStandby_l(); | 
| Haynes Mathew George | 4c6a433 | 2014-01-15 12:31:39 -0800 | [diff] [blame] | 687 | virtual     void        onAddNewTrack_l(); | 
| Haynes Mathew George | 4527b9e | 2016-07-07 19:54:17 -0700 | [diff] [blame] | 688 | void        onAsyncError(); // error reported by AsyncCallbackThread | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 689 |  | 
|  | 690 | // ThreadBase virtuals | 
|  | 691 | virtual     void        preExit(); | 
|  | 692 |  | 
| Eric Laurent | 6466797 | 2016-03-30 18:19:46 -0700 | [diff] [blame] | 693 | virtual     bool        keepWakeLock() const { return true; } | 
| Andy Hung | dae2770 | 2016-10-31 14:01:16 -0700 | [diff] [blame] | 694 | virtual     void        acquireWakeLock_l() { | 
|  | 695 | ThreadBase::acquireWakeLock_l(); | 
|  | 696 | mActiveTracks.updatePowerState(this, true /* force */); | 
|  | 697 | } | 
| Eric Laurent | 6466797 | 2016-03-30 18:19:46 -0700 | [diff] [blame] | 698 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 699 | public: | 
|  | 700 |  | 
|  | 701 | virtual     status_t    initCheck() const { return (mOutput == NULL) ? NO_INIT : NO_ERROR; } | 
|  | 702 |  | 
|  | 703 | // return estimated latency in milliseconds, as reported by HAL | 
|  | 704 | uint32_t    latency() const; | 
|  | 705 | // same, but lock must already be held | 
|  | 706 | uint32_t    latency_l() const; | 
|  | 707 |  | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 708 | // VolumeInterface | 
|  | 709 | virtual     void        setMasterVolume(float value); | 
|  | 710 | virtual     void        setMasterMute(bool muted); | 
|  | 711 | virtual     void        setStreamVolume(audio_stream_type_t stream, float value); | 
|  | 712 | virtual     void        setStreamMute(audio_stream_type_t stream, bool muted); | 
|  | 713 | virtual     float       streamVolume(audio_stream_type_t stream) const; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 714 |  | 
|  | 715 | sp<Track>   createTrack_l( | 
|  | 716 | const sp<AudioFlinger::Client>& client, | 
|  | 717 | audio_stream_type_t streamType, | 
| Kevin Rocard | 1f564ac | 2018-03-29 13:53:10 -0700 | [diff] [blame] | 718 | const audio_attributes_t& attr, | 
| Eric Laurent | 21da647 | 2017-11-09 16:29:26 -0800 | [diff] [blame] | 719 | uint32_t *sampleRate, | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 720 | audio_format_t format, | 
|  | 721 | audio_channel_mask_t channelMask, | 
| Glenn Kasten | 74935e4 | 2013-12-19 08:56:45 -0800 | [diff] [blame] | 722 | size_t *pFrameCount, | 
| Eric Laurent | 21da647 | 2017-11-09 16:29:26 -0800 | [diff] [blame] | 723 | size_t *pNotificationFrameCount, | 
|  | 724 | uint32_t notificationsPerBuffer, | 
|  | 725 | float speed, | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 726 | const sp<IMemory>& sharedBuffer, | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 727 | audio_session_t sessionId, | 
| Eric Laurent | 0506778 | 2016-06-01 18:27:28 -0700 | [diff] [blame] | 728 | audio_output_flags_t *flags, | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 729 | pid_t tid, | 
| Andy Hung | 1f12a8a | 2016-11-07 16:10:30 -0800 | [diff] [blame] | 730 | uid_t uid, | 
| Eric Laurent | 20b9ef0 | 2016-12-05 11:03:16 -0800 | [diff] [blame] | 731 | status_t *status /*non-NULL*/, | 
|  | 732 | audio_port_handle_t portId); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 733 |  | 
|  | 734 | AudioStreamOut* getOutput() const; | 
|  | 735 | AudioStreamOut* clearOutput(); | 
| Mikhail Naganov | 1dc9867 | 2016-08-18 17:50:29 -0700 | [diff] [blame] | 736 | virtual sp<StreamHalInterface> stream() const; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 737 |  | 
|  | 738 | // a very large number of suspend() will eventually wraparound, but unlikely | 
|  | 739 | void        suspend() { (void) android_atomic_inc(&mSuspended); } | 
|  | 740 | void        restore() | 
|  | 741 | { | 
|  | 742 | // if restore() is done without suspend(), get back into | 
|  | 743 | // range so that the next suspend() will operate correctly | 
|  | 744 | if (android_atomic_dec(&mSuspended) <= 0) { | 
|  | 745 | android_atomic_release_store(0, &mSuspended); | 
|  | 746 | } | 
|  | 747 | } | 
|  | 748 | bool        isSuspended() const | 
|  | 749 | { return android_atomic_acquire_load(&mSuspended) > 0; } | 
|  | 750 |  | 
|  | 751 | virtual     String8     getParameters(const String8& keys); | 
| Eric Laurent | 7c1ec5f | 2015-07-09 14:52:47 -0700 | [diff] [blame] | 752 | virtual     void        ioConfigChanged(audio_io_config_event event, pid_t pid = 0); | 
| Kévin PETIT | 377b2ec | 2014-02-03 12:35:36 +0000 | [diff] [blame] | 753 | status_t    getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames); | 
| Andy Hung | 010a1a1 | 2014-03-13 13:57:33 -0700 | [diff] [blame] | 754 | // Consider also removing and passing an explicit mMainBuffer initialization | 
|  | 755 | // parameter to AF::PlaybackThread::Track::Track(). | 
| rago | 94a1ee8 | 2017-07-21 15:11:02 -0700 | [diff] [blame] | 756 | effect_buffer_t *sinkBuffer() const { | 
|  | 757 | return reinterpret_cast<effect_buffer_t *>(mSinkBuffer); }; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 758 |  | 
|  | 759 | virtual     void detachAuxEffect_l(int effectId); | 
| Chih-Hung Hsieh | e964d4e | 2016-08-09 14:31:32 -0700 | [diff] [blame] | 760 | status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track>& track, | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 761 | int EffectId); | 
| Chih-Hung Hsieh | e964d4e | 2016-08-09 14:31:32 -0700 | [diff] [blame] | 762 | status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track>& track, | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 763 | int EffectId); | 
|  | 764 |  | 
|  | 765 | virtual status_t addEffectChain_l(const sp<EffectChain>& chain); | 
|  | 766 | virtual size_t removeEffectChain_l(const sp<EffectChain>& chain); | 
| Eric Laurent | 4c41506 | 2016-06-17 16:14:16 -0700 | [diff] [blame] | 767 | virtual uint32_t hasAudioSession_l(audio_session_t sessionId) const; | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 768 | virtual uint32_t getStrategyForSession_l(audio_session_t sessionId); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 769 |  | 
|  | 770 |  | 
|  | 771 | virtual status_t setSyncEvent(const sp<SyncEvent>& event); | 
|  | 772 | virtual bool     isValidSyncEvent(const sp<SyncEvent>& event) const; | 
| Glenn Kasten | fb1fdc9 | 2013-07-10 17:03:19 -0700 | [diff] [blame] | 773 |  | 
|  | 774 | // called with AudioFlinger lock held | 
| Eric Laurent | 1308462 | 2016-05-17 10:51:49 -0700 | [diff] [blame] | 775 | bool     invalidateTracks_l(audio_stream_type_t streamType); | 
| Haynes Mathew George | 05317d2 | 2016-05-03 16:34:26 -0700 | [diff] [blame] | 776 | virtual void     invalidateTracks(audio_stream_type_t streamType); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 777 |  | 
| Glenn Kasten | 9b58f63 | 2013-07-16 11:37:48 -0700 | [diff] [blame] | 778 | virtual     size_t      frameCount() const { return mNormalFrameCount; } | 
|  | 779 |  | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 780 | status_t    getTimestamp_l(AudioTimestamp& timestamp); | 
|  | 781 |  | 
|  | 782 | void        addPatchTrack(const sp<PatchTrack>& track); | 
|  | 783 | void        deletePatchTrack(const sp<PatchTrack>& track); | 
|  | 784 |  | 
|  | 785 | virtual     void        getAudioPortConfig(struct audio_port_config *config); | 
| Eric Laurent | accc147 | 2013-09-20 09:36:34 -0700 | [diff] [blame] | 786 |  | 
| Andy Hung | 10cbff1 | 2017-02-21 17:30:14 -0800 | [diff] [blame] | 787 | // Return the asynchronous signal wait time. | 
|  | 788 | virtual     int64_t     computeWaitTimeNs_l() const { return INT64_MAX; } | 
|  | 789 |  | 
| Andy Hung | 293558a | 2017-03-21 12:19:20 -0700 | [diff] [blame] | 790 | virtual     bool        isOutput() const override { return true; } | 
|  | 791 |  | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 792 | // returns true if the track is allowed to be added to the thread. | 
|  | 793 | virtual     bool        isTrackAllowed_l( | 
|  | 794 | audio_channel_mask_t channelMask __unused, | 
|  | 795 | audio_format_t format __unused, | 
|  | 796 | audio_session_t sessionId __unused, | 
|  | 797 | uid_t uid) const { | 
|  | 798 | return trackCountForUid_l(uid) < PlaybackThread::kMaxTracksPerUid | 
|  | 799 | && mTracks.size() < PlaybackThread::kMaxTracks; | 
|  | 800 | } | 
|  | 801 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 802 | protected: | 
| Glenn Kasten | deca2ae | 2014-02-07 10:25:56 -0800 | [diff] [blame] | 803 | // updated by readOutputParameters_l() | 
| Glenn Kasten | 9b58f63 | 2013-07-16 11:37:48 -0700 | [diff] [blame] | 804 | size_t                          mNormalFrameCount;  // normal mixer and effects | 
|  | 805 |  | 
| Andy Hung | 08fb174 | 2015-05-31 23:22:10 -0700 | [diff] [blame] | 806 | bool                            mThreadThrottle;     // throttle the thread processing | 
| Andy Hung | 40eb1a1 | 2015-06-18 13:42:02 -0700 | [diff] [blame] | 807 | uint32_t                        mThreadThrottleTimeMs; // throttle time for MIXER threads | 
|  | 808 | uint32_t                        mThreadThrottleEndMs;  // notify once per throttling | 
| Andy Hung | 08fb174 | 2015-05-31 23:22:10 -0700 | [diff] [blame] | 809 | uint32_t                        mHalfBufferMs;       // half the buffer size in milliseconds | 
|  | 810 |  | 
| Andy Hung | 010a1a1 | 2014-03-13 13:57:33 -0700 | [diff] [blame] | 811 | void*                           mSinkBuffer;         // frame size aligned sink buffer | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 812 |  | 
| Andy Hung | 98ef978 | 2014-03-04 14:46:50 -0800 | [diff] [blame] | 813 | // TODO: | 
|  | 814 | // Rearrange the buffer info into a struct/class with | 
|  | 815 | // clear, copy, construction, destruction methods. | 
|  | 816 | // | 
|  | 817 | // mSinkBuffer also has associated with it: | 
|  | 818 | // | 
|  | 819 | // mSinkBufferSize: Sink Buffer Size | 
|  | 820 | // mFormat: Sink Buffer Format | 
|  | 821 |  | 
| Andy Hung | 69aed5f | 2014-02-25 17:24:40 -0800 | [diff] [blame] | 822 | // Mixer Buffer (mMixerBuffer*) | 
|  | 823 | // | 
|  | 824 | // In the case of floating point or multichannel data, which is not in the | 
|  | 825 | // sink format, it is required to accumulate in a higher precision or greater channel count | 
|  | 826 | // buffer before downmixing or data conversion to the sink buffer. | 
|  | 827 |  | 
|  | 828 | // Set to "true" to enable the Mixer Buffer otherwise mixer output goes to sink buffer. | 
|  | 829 | bool                            mMixerBufferEnabled; | 
|  | 830 |  | 
|  | 831 | // Storage, 32 byte aligned (may make this alignment a requirement later). | 
|  | 832 | // Due to constraints on mNormalFrameCount, the buffer size is a multiple of 16 frames. | 
|  | 833 | void*                           mMixerBuffer; | 
|  | 834 |  | 
|  | 835 | // Size of mMixerBuffer in bytes: mNormalFrameCount * #channels * sampsize. | 
|  | 836 | size_t                          mMixerBufferSize; | 
|  | 837 |  | 
|  | 838 | // The audio format of mMixerBuffer. Set to AUDIO_FORMAT_PCM_(FLOAT|16_BIT) only. | 
|  | 839 | audio_format_t                  mMixerBufferFormat; | 
|  | 840 |  | 
|  | 841 | // An internal flag set to true by MixerThread::prepareTracks_l() | 
|  | 842 | // when mMixerBuffer contains valid data after mixing. | 
|  | 843 | bool                            mMixerBufferValid; | 
|  | 844 |  | 
| Andy Hung | 98ef978 | 2014-03-04 14:46:50 -0800 | [diff] [blame] | 845 | // Effects Buffer (mEffectsBuffer*) | 
|  | 846 | // | 
|  | 847 | // In the case of effects data, which is not in the sink format, | 
|  | 848 | // it is required to accumulate in a different buffer before data conversion | 
|  | 849 | // to the sink buffer. | 
|  | 850 |  | 
|  | 851 | // Set to "true" to enable the Effects Buffer otherwise effects output goes to sink buffer. | 
|  | 852 | bool                            mEffectBufferEnabled; | 
|  | 853 |  | 
|  | 854 | // Storage, 32 byte aligned (may make this alignment a requirement later). | 
|  | 855 | // Due to constraints on mNormalFrameCount, the buffer size is a multiple of 16 frames. | 
|  | 856 | void*                           mEffectBuffer; | 
|  | 857 |  | 
|  | 858 | // Size of mEffectsBuffer in bytes: mNormalFrameCount * #channels * sampsize. | 
|  | 859 | size_t                          mEffectBufferSize; | 
|  | 860 |  | 
|  | 861 | // The audio format of mEffectsBuffer. Set to AUDIO_FORMAT_PCM_16_BIT only. | 
|  | 862 | audio_format_t                  mEffectBufferFormat; | 
|  | 863 |  | 
|  | 864 | // An internal flag set to true by MixerThread::prepareTracks_l() | 
|  | 865 | // when mEffectsBuffer contains valid data after mixing. | 
|  | 866 | // | 
|  | 867 | // When this is set, all mixer data is routed into the effects buffer | 
|  | 868 | // for any processing (including output processing). | 
|  | 869 | bool                            mEffectBufferValid; | 
|  | 870 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 871 | // suspend count, > 0 means suspended.  While suspended, the thread continues to pull from | 
|  | 872 | // tracks and mix, but doesn't write to HAL.  A2DP and SCO HAL implementations can't handle | 
|  | 873 | // concurrent use of both of them, so Audio Policy Service suspends one of the threads to | 
|  | 874 | // workaround that restriction. | 
|  | 875 | // 'volatile' means accessed via atomic operations and no lock. | 
|  | 876 | volatile int32_t                mSuspended; | 
|  | 877 |  | 
| Andy Hung | 818e7a3 | 2016-02-16 18:08:07 -0800 | [diff] [blame] | 878 | int64_t                         mBytesWritten; | 
| Andy Hung | c54b1ff | 2016-02-23 14:07:07 -0800 | [diff] [blame] | 879 | int64_t                         mFramesWritten; // not reset on standby | 
| Andy Hung | 238fa3d | 2016-07-28 10:53:22 -0700 | [diff] [blame] | 880 | int64_t                         mSuspendedFrames; // not reset on standby | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 881 | private: | 
|  | 882 | // mMasterMute is in both PlaybackThread and in AudioFlinger.  When a | 
|  | 883 | // PlaybackThread needs to find out if master-muted, it checks it's local | 
|  | 884 | // copy rather than the one in AudioFlinger.  This optimization saves a lock. | 
|  | 885 | bool                            mMasterMute; | 
|  | 886 | void        setMasterMute_l(bool muted) { mMasterMute = muted; } | 
|  | 887 | protected: | 
| Andy Hung | dae2770 | 2016-10-31 14:01:16 -0700 | [diff] [blame] | 888 | ActiveTracks<Track>     mActiveTracks; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 889 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 890 | // Time to sleep between cycles when: | 
|  | 891 | virtual uint32_t        activeSleepTimeUs() const;      // mixer state MIXER_TRACKS_ENABLED | 
|  | 892 | virtual uint32_t        idleSleepTimeUs() const = 0;    // mixer state MIXER_IDLE | 
|  | 893 | virtual uint32_t        suspendSleepTimeUs() const = 0; // audio policy manager suspended us | 
|  | 894 | // No sleep when mixer state == MIXER_TRACKS_READY; relies on audio HAL stream->write() | 
|  | 895 | // No sleep in standby mode; waits on a condition | 
|  | 896 |  | 
|  | 897 | // Code snippets that are temporarily lifted up out of threadLoop() until the merge | 
|  | 898 | void        checkSilentMode_l(); | 
|  | 899 |  | 
|  | 900 | // Non-trivial for DUPLICATING only | 
|  | 901 | virtual     void        saveOutputTracks() { } | 
|  | 902 | virtual     void        clearOutputTracks() { } | 
|  | 903 |  | 
|  | 904 | // Cache various calculated values, at threadLoop() entry and after a parameter change | 
|  | 905 | virtual     void        cacheParameters_l(); | 
|  | 906 |  | 
|  | 907 | virtual     uint32_t    correctLatency_l(uint32_t latency) const; | 
|  | 908 |  | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 909 | virtual     status_t    createAudioPatch_l(const struct audio_patch *patch, | 
|  | 910 | audio_patch_handle_t *handle); | 
|  | 911 | virtual     status_t    releaseAudioPatch_l(const audio_patch_handle_t handle); | 
|  | 912 |  | 
| Phil Burk | 6fc2a7c | 2015-04-30 16:08:10 -0700 | [diff] [blame] | 913 | bool        usesHwAvSync() const { return (mType == DIRECT) && (mOutput != NULL) | 
|  | 914 | && mHwSupportsPause | 
|  | 915 | && (mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC); } | 
| Eric Laurent | 0f7b5f2 | 2014-12-19 10:43:21 -0800 | [diff] [blame] | 916 |  | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 917 | uint32_t    trackCountForUid_l(uid_t uid) const; | 
| Eric Laurent | ad7dd96 | 2016-09-22 12:38:37 -0700 | [diff] [blame] | 918 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 919 | private: | 
|  | 920 |  | 
|  | 921 | friend class AudioFlinger;      // for numerous | 
|  | 922 |  | 
| Mikhail Naganov | bf49308 | 2017-04-17 17:37:12 -0700 | [diff] [blame] | 923 | DISALLOW_COPY_AND_ASSIGN(PlaybackThread); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 924 |  | 
|  | 925 | status_t    addTrack_l(const sp<Track>& track); | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 926 | bool        destroyTrack_l(const sp<Track>& track); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 927 | void        removeTrack_l(const sp<Track>& track); | 
|  | 928 |  | 
| Glenn Kasten | deca2ae | 2014-02-07 10:25:56 -0800 | [diff] [blame] | 929 | void        readOutputParameters_l(); | 
| Kevin Rocard | c86a7f7 | 2018-04-03 09:00:09 -0700 | [diff] [blame] | 930 | void        updateMetadata_l() final; | 
|  | 931 | virtual void sendMetadataToBackend_l(const StreamOutHalInterface::SourceMetadata& metadata); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 932 |  | 
|  | 933 | virtual void dumpInternals(int fd, const Vector<String16>& args); | 
|  | 934 | void        dumpTracks(int fd, const Vector<String16>& args); | 
|  | 935 |  | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 936 | // The Tracks class manages names for all tracks | 
|  | 937 | // added and removed from the Thread. | 
|  | 938 | template <typename T> | 
|  | 939 | class Tracks { | 
|  | 940 | public: | 
|  | 941 | Tracks(bool saveDeletedTrackNames) : | 
|  | 942 | mSaveDeletedTrackNames(saveDeletedTrackNames) { } | 
|  | 943 |  | 
|  | 944 | // SortedVector methods | 
|  | 945 | ssize_t         add(const sp<T> &track); | 
|  | 946 | ssize_t         remove(const sp<T> &track); | 
|  | 947 | size_t          size() const { | 
|  | 948 | return mTracks.size(); | 
|  | 949 | } | 
|  | 950 | bool            isEmpty() const { | 
|  | 951 | return mTracks.isEmpty(); | 
|  | 952 | } | 
|  | 953 | ssize_t         indexOf(const sp<T> &item) { | 
|  | 954 | return mTracks.indexOf(item); | 
|  | 955 | } | 
|  | 956 | sp<T>           operator[](size_t index) const { | 
|  | 957 | return mTracks[index]; | 
|  | 958 | } | 
|  | 959 | typename SortedVector<sp<T>>::iterator begin() { | 
|  | 960 | return mTracks.begin(); | 
|  | 961 | } | 
|  | 962 | typename SortedVector<sp<T>>::iterator end() { | 
|  | 963 | return mTracks.end(); | 
|  | 964 | } | 
|  | 965 |  | 
|  | 966 | size_t          processDeletedTrackNames(std::function<void(int)> f) { | 
|  | 967 | const size_t size = mDeletedTrackNames.size(); | 
|  | 968 | if (size > 0) { | 
|  | 969 | for (const int name : mDeletedTrackNames) { | 
|  | 970 | f(name); | 
|  | 971 | } | 
|  | 972 | } | 
|  | 973 | return size; | 
|  | 974 | } | 
|  | 975 |  | 
|  | 976 | void            clearDeletedTrackNames() { mDeletedTrackNames.clear(); } | 
|  | 977 |  | 
|  | 978 | private: | 
|  | 979 | // Track names pending deletion for MIXER type threads | 
|  | 980 | const bool mSaveDeletedTrackNames; // true to enable tracking | 
|  | 981 | std::set<int> mDeletedTrackNames; | 
|  | 982 |  | 
|  | 983 | // Fast lookup of previously deleted track names for reuse. | 
|  | 984 | // This is an arbitrary decision (actually any non-negative | 
|  | 985 | // integer that isn't in mTracks[*]->names() could be used) - we attempt | 
|  | 986 | // to use the smallest possible available name. | 
|  | 987 | std::set<int> mUnusedTrackNames; | 
|  | 988 |  | 
|  | 989 | SortedVector<sp<T>> mTracks; // wrapped SortedVector. | 
|  | 990 | }; | 
|  | 991 |  | 
|  | 992 | Tracks<Track>                   mTracks; | 
|  | 993 |  | 
| Eric Laurent | 223fd5c | 2014-11-11 13:43:36 -0800 | [diff] [blame] | 994 | stream_type_t                   mStreamTypes[AUDIO_STREAM_CNT]; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 995 | AudioStreamOut                  *mOutput; | 
|  | 996 |  | 
|  | 997 | float                           mMasterVolume; | 
|  | 998 | nsecs_t                         mLastWriteTime; | 
|  | 999 | int                             mNumWrites; | 
|  | 1000 | int                             mNumDelayedWrites; | 
|  | 1001 | bool                            mInWrite; | 
|  | 1002 |  | 
|  | 1003 | // FIXME rename these former local variables of threadLoop to standard "m" names | 
| Eric Laurent | ad9cb8b | 2015-05-26 16:38:19 -0700 | [diff] [blame] | 1004 | nsecs_t                         mStandbyTimeNs; | 
| Andy Hung | 25c2dac | 2014-02-27 14:56:00 -0800 | [diff] [blame] | 1005 | size_t                          mSinkBufferSize; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1006 |  | 
|  | 1007 | // cached copies of activeSleepTimeUs() and idleSleepTimeUs() made by cacheParameters_l() | 
| Eric Laurent | ad9cb8b | 2015-05-26 16:38:19 -0700 | [diff] [blame] | 1008 | uint32_t                        mActiveSleepTimeUs; | 
|  | 1009 | uint32_t                        mIdleSleepTimeUs; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1010 |  | 
| Eric Laurent | ad9cb8b | 2015-05-26 16:38:19 -0700 | [diff] [blame] | 1011 | uint32_t                        mSleepTimeUs; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1012 |  | 
|  | 1013 | // mixer status returned by prepareTracks_l() | 
|  | 1014 | mixer_state                     mMixerStatus; // current cycle | 
|  | 1015 | // previous cycle when in prepareTracks_l() | 
|  | 1016 | mixer_state                     mMixerStatusIgnoringFastTracks; | 
|  | 1017 | // FIXME or a separate ready state per track | 
|  | 1018 |  | 
|  | 1019 | // FIXME move these declarations into the specific sub-class that needs them | 
|  | 1020 | // MIXER only | 
|  | 1021 | uint32_t                        sleepTimeShift; | 
|  | 1022 |  | 
|  | 1023 | // same as AudioFlinger::mStandbyTimeInNsecs except for DIRECT which uses a shorter value | 
| Eric Laurent | ad9cb8b | 2015-05-26 16:38:19 -0700 | [diff] [blame] | 1024 | nsecs_t                         mStandbyDelayNs; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1025 |  | 
|  | 1026 | // MIXER only | 
|  | 1027 | nsecs_t                         maxPeriod; | 
|  | 1028 |  | 
|  | 1029 | // DUPLICATING only | 
|  | 1030 | uint32_t                        writeFrames; | 
|  | 1031 |  | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1032 | size_t                          mBytesRemaining; | 
|  | 1033 | size_t                          mCurrentWriteLength; | 
|  | 1034 | bool                            mUseAsyncWrite; | 
| Eric Laurent | 3b4529e | 2013-09-05 18:09:19 -0700 | [diff] [blame] | 1035 | // mWriteAckSequence contains current write sequence on bits 31-1. The write sequence is | 
|  | 1036 | // incremented each time a write(), a flush() or a standby() occurs. | 
|  | 1037 | // Bit 0 is set when a write blocks and indicates a callback is expected. | 
|  | 1038 | // Bit 0 is reset by the async callback thread calling resetWriteBlocked(). Out of sequence | 
|  | 1039 | // callbacks are ignored. | 
|  | 1040 | uint32_t                        mWriteAckSequence; | 
|  | 1041 | // mDrainSequence contains current drain sequence on bits 31-1. The drain sequence is | 
|  | 1042 | // incremented each time a drain is requested or a flush() or standby() occurs. | 
|  | 1043 | // Bit 0 is set when the drain() command is called at the HAL and indicates a callback is | 
|  | 1044 | // expected. | 
|  | 1045 | // Bit 0 is reset by the async callback thread calling resetDraining(). Out of sequence | 
|  | 1046 | // callbacks are ignored. | 
|  | 1047 | uint32_t                        mDrainSequence; | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1048 | sp<AsyncCallbackThread>         mCallbackThread; | 
|  | 1049 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1050 | private: | 
|  | 1051 | // The HAL output sink is treated as non-blocking, but current implementation is blocking | 
|  | 1052 | sp<NBAIO_Sink>          mOutputSink; | 
|  | 1053 | // If a fast mixer is present, the blocking pipe sink, otherwise clear | 
|  | 1054 | sp<NBAIO_Sink>          mPipeSink; | 
|  | 1055 | // The current sink for the normal mixer to write it's (sub)mix, mOutputSink or mPipeSink | 
|  | 1056 | sp<NBAIO_Sink>          mNormalSink; | 
| Glenn Kasten | 46909e7 | 2013-02-26 09:20:22 -0800 | [diff] [blame] | 1057 | #ifdef TEE_SINK | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1058 | // For dumpsys | 
|  | 1059 | sp<NBAIO_Sink>          mTeeSink; | 
|  | 1060 | sp<NBAIO_Source>        mTeeSource; | 
| Glenn Kasten | 46909e7 | 2013-02-26 09:20:22 -0800 | [diff] [blame] | 1061 | #endif | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1062 | uint32_t                mScreenState;   // cached copy of gScreenState | 
| Sanna Catherine de Treville Wager | 2a6a945 | 2017-07-28 11:02:01 -0700 | [diff] [blame] | 1063 | // TODO: add comment and adjust size as needed | 
| Glenn Kasten | eef598c | 2017-04-03 14:41:13 -0700 | [diff] [blame] | 1064 | static const size_t     kFastMixerLogSize = 8 * 1024; | 
| Glenn Kasten | 9e58b55 | 2013-01-18 15:09:48 -0800 | [diff] [blame] | 1065 | sp<NBLog::Writer>       mFastMixerNBLogWriter; | 
| Andy Hung | 2148bf0 | 2016-11-28 19:01:02 -0800 | [diff] [blame] | 1066 |  | 
| Andy Hung | 2148bf0 | 2016-11-28 19:01:02 -0800 | [diff] [blame] | 1067 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1068 | public: | 
|  | 1069 | virtual     bool        hasFastMixer() const = 0; | 
| Glenn Kasten | 0f11b51 | 2014-01-31 16:18:54 -0800 | [diff] [blame] | 1070 | virtual     FastTrackUnderruns getFastTrackUnderruns(size_t fastIndex __unused) const | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1071 | { FastTrackUnderruns dummy; return dummy; } | 
|  | 1072 |  | 
|  | 1073 | protected: | 
|  | 1074 | // accessed by both binder threads and within threadLoop(), lock on mutex needed | 
|  | 1075 | unsigned    mFastTrackAvailMask;    // bit i set if fast track [i] is available | 
| Eric Laurent | d1f69b0 | 2014-12-15 14:33:13 -0800 | [diff] [blame] | 1076 | bool        mHwSupportsPause; | 
|  | 1077 | bool        mHwPaused; | 
|  | 1078 | bool        mFlushPending; | 
| Eric Laurent | 7c29ec9 | 2017-09-20 17:54:22 -0700 | [diff] [blame] | 1079 | // volumes last sent to audio HAL with stream->setVolume() | 
|  | 1080 | float mLeftVolFloat; | 
|  | 1081 | float mRightVolFloat; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1082 | }; | 
|  | 1083 |  | 
|  | 1084 | class MixerThread : public PlaybackThread { | 
|  | 1085 | public: | 
|  | 1086 | MixerThread(const sp<AudioFlinger>& audioFlinger, | 
|  | 1087 | AudioStreamOut* output, | 
|  | 1088 | audio_io_handle_t id, | 
|  | 1089 | audio_devices_t device, | 
| Eric Laurent | 72e3f39 | 2015-05-20 14:43:50 -0700 | [diff] [blame] | 1090 | bool systemReady, | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1091 | type_t type = MIXER); | 
|  | 1092 | virtual             ~MixerThread(); | 
|  | 1093 |  | 
|  | 1094 | // Thread virtuals | 
|  | 1095 |  | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 1096 | virtual     bool        checkForNewParameter_l(const String8& keyValuePair, | 
|  | 1097 | status_t& status); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1098 | virtual     void        dumpInternals(int fd, const Vector<String16>& args); | 
|  | 1099 |  | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 1100 | virtual     bool        isTrackAllowed_l( | 
|  | 1101 | audio_channel_mask_t channelMask, audio_format_t format, | 
|  | 1102 | audio_session_t sessionId, uid_t uid) const override; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1103 | protected: | 
|  | 1104 | virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1105 | virtual     uint32_t    idleSleepTimeUs() const; | 
|  | 1106 | virtual     uint32_t    suspendSleepTimeUs() const; | 
|  | 1107 | virtual     void        cacheParameters_l(); | 
|  | 1108 |  | 
| Andy Hung | dae2770 | 2016-10-31 14:01:16 -0700 | [diff] [blame] | 1109 | virtual void acquireWakeLock_l() { | 
|  | 1110 | PlaybackThread::acquireWakeLock_l(); | 
| Andy Hung | 818e7a3 | 2016-02-16 18:08:07 -0800 | [diff] [blame] | 1111 | if (hasFastMixer()) { | 
|  | 1112 | mFastMixer->setBoottimeOffset( | 
|  | 1113 | mTimestamp.mTimebaseOffset[ExtendedTimestamp::TIMEBASE_BOOTTIME]); | 
|  | 1114 | } | 
|  | 1115 | } | 
|  | 1116 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1117 | // threadLoop snippets | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1118 | virtual     ssize_t     threadLoop_write(); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1119 | virtual     void        threadLoop_standby(); | 
|  | 1120 | virtual     void        threadLoop_mix(); | 
|  | 1121 | virtual     void        threadLoop_sleepTime(); | 
|  | 1122 | virtual     void        threadLoop_removeTracks(const Vector< sp<Track> >& tracksToRemove); | 
|  | 1123 | virtual     uint32_t    correctLatency_l(uint32_t latency) const; | 
|  | 1124 |  | 
| Eric Laurent | 054d9d3 | 2015-04-24 08:48:48 -0700 | [diff] [blame] | 1125 | virtual     status_t    createAudioPatch_l(const struct audio_patch *patch, | 
|  | 1126 | audio_patch_handle_t *handle); | 
|  | 1127 | virtual     status_t    releaseAudioPatch_l(const audio_patch_handle_t handle); | 
|  | 1128 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1129 | AudioMixer* mAudioMixer;    // normal mixer | 
|  | 1130 | private: | 
|  | 1131 | // one-time initialization, no locks required | 
| Glenn Kasten | 4d23ca3 | 2014-05-13 10:39:51 -0700 | [diff] [blame] | 1132 | sp<FastMixer>     mFastMixer;     // non-0 if there is also a fast mixer | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1133 | sp<AudioWatchdog> mAudioWatchdog; // non-0 if there is an audio watchdog thread | 
|  | 1134 |  | 
|  | 1135 | // contents are not guaranteed to be consistent, no locks required | 
|  | 1136 | FastMixerDumpState mFastMixerDumpState; | 
|  | 1137 | #ifdef STATE_QUEUE_DUMP | 
|  | 1138 | StateQueueObserverDump mStateQueueObserverDump; | 
|  | 1139 | StateQueueMutatorDump  mStateQueueMutatorDump; | 
|  | 1140 | #endif | 
|  | 1141 | AudioWatchdogDump mAudioWatchdogDump; | 
|  | 1142 |  | 
|  | 1143 | // accessible only within the threadLoop(), no locks required | 
|  | 1144 | //          mFastMixer->sq()    // for mutating and pushing state | 
|  | 1145 | int32_t     mFastMixerFutex;    // for cold idle | 
|  | 1146 |  | 
| Andy Hung | 2ddee19 | 2015-12-18 17:34:44 -0800 | [diff] [blame] | 1147 | std::atomic_bool mMasterMono; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1148 | public: | 
| Glenn Kasten | 4d23ca3 | 2014-05-13 10:39:51 -0700 | [diff] [blame] | 1149 | virtual     bool        hasFastMixer() const { return mFastMixer != 0; } | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1150 | virtual     FastTrackUnderruns getFastTrackUnderruns(size_t fastIndex) const { | 
| Glenn Kasten | dc2c50b | 2016-04-21 08:13:14 -0700 | [diff] [blame] | 1151 | ALOG_ASSERT(fastIndex < FastMixerState::sMaxFastTracks); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1152 | return mFastMixerDumpState.mTracks[fastIndex].mUnderruns; | 
|  | 1153 | } | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 1154 |  | 
| Andy Hung | 2ddee19 | 2015-12-18 17:34:44 -0800 | [diff] [blame] | 1155 | protected: | 
|  | 1156 | virtual     void       setMasterMono_l(bool mono) { | 
|  | 1157 | mMasterMono.store(mono); | 
|  | 1158 | if (mFastMixer != nullptr) { /* hasFastMixer() */ | 
|  | 1159 | mFastMixer->setMasterMono(mMasterMono); | 
|  | 1160 | } | 
|  | 1161 | } | 
|  | 1162 | // the FastMixer performs mono blend if it exists. | 
| Glenn Kasten | 03c48d5 | 2016-01-27 17:25:17 -0800 | [diff] [blame] | 1163 | // Blending with limiter is not idempotent, | 
|  | 1164 | // and blending without limiter is idempotent but inefficient to do twice. | 
| Andy Hung | 2ddee19 | 2015-12-18 17:34:44 -0800 | [diff] [blame] | 1165 | virtual     bool       requireMonoBlend() { return mMasterMono.load() && !hasFastMixer(); } | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1166 | }; | 
|  | 1167 |  | 
|  | 1168 | class DirectOutputThread : public PlaybackThread { | 
|  | 1169 | public: | 
|  | 1170 |  | 
|  | 1171 | DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, | 
| Eric Laurent | e93cc03 | 2016-05-05 10:15:10 -0700 | [diff] [blame] | 1172 | audio_io_handle_t id, audio_devices_t device, bool systemReady); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1173 | virtual                 ~DirectOutputThread(); | 
|  | 1174 |  | 
|  | 1175 | // Thread virtuals | 
|  | 1176 |  | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 1177 | virtual     bool        checkForNewParameter_l(const String8& keyValuePair, | 
|  | 1178 | status_t& status); | 
| Eric Laurent | e659ef4 | 2014-09-29 13:06:46 -0700 | [diff] [blame] | 1179 | virtual     void        flushHw_l(); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1180 |  | 
|  | 1181 | protected: | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1182 | virtual     uint32_t    activeSleepTimeUs() const; | 
|  | 1183 | virtual     uint32_t    idleSleepTimeUs() const; | 
|  | 1184 | virtual     uint32_t    suspendSleepTimeUs() const; | 
|  | 1185 | virtual     void        cacheParameters_l(); | 
|  | 1186 |  | 
|  | 1187 | // threadLoop snippets | 
|  | 1188 | virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove); | 
|  | 1189 | virtual     void        threadLoop_mix(); | 
|  | 1190 | virtual     void        threadLoop_sleepTime(); | 
| Eric Laurent | d1f69b0 | 2014-12-15 14:33:13 -0800 | [diff] [blame] | 1191 | virtual     void        threadLoop_exit(); | 
|  | 1192 | virtual     bool        shouldStandby_l(); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1193 |  | 
| Phil Burk | 43b4dcc | 2015-06-09 16:53:44 -0700 | [diff] [blame] | 1194 | virtual     void        onAddNewTrack_l(); | 
|  | 1195 |  | 
| Andy Hung | 10cbff1 | 2017-02-21 17:30:14 -0800 | [diff] [blame] | 1196 | bool mVolumeShaperActive; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1197 |  | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1198 | DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, | 
| Eric Laurent | 72e3f39 | 2015-05-20 14:43:50 -0700 | [diff] [blame] | 1199 | audio_io_handle_t id, uint32_t device, ThreadBase::type_t type, | 
| Eric Laurent | e93cc03 | 2016-05-05 10:15:10 -0700 | [diff] [blame] | 1200 | bool systemReady); | 
| Eric Laurent | 5850c4c | 2016-11-10 13:04:31 -0800 | [diff] [blame] | 1201 | void processVolume_l(Track *track, bool lastTrack); | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1202 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1203 | // prepareTracks_l() tells threadLoop_mix() the name of the single active track | 
|  | 1204 | sp<Track>               mActiveTrack; | 
| Phil Burk | 43b4dcc | 2015-06-09 16:53:44 -0700 | [diff] [blame] | 1205 |  | 
|  | 1206 | wp<Track>               mPreviousTrack;         // used to detect track switch | 
|  | 1207 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1208 | public: | 
|  | 1209 | virtual     bool        hasFastMixer() const { return false; } | 
| Andy Hung | 10cbff1 | 2017-02-21 17:30:14 -0800 | [diff] [blame] | 1210 |  | 
|  | 1211 | virtual     int64_t     computeWaitTimeNs_l() const override; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1212 | }; | 
|  | 1213 |  | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1214 | class OffloadThread : public DirectOutputThread { | 
|  | 1215 | public: | 
|  | 1216 |  | 
|  | 1217 | OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, | 
| Eric Laurent | e93cc03 | 2016-05-05 10:15:10 -0700 | [diff] [blame] | 1218 | audio_io_handle_t id, uint32_t device, bool systemReady); | 
| Eric Laurent | 6a51d7e | 2013-10-17 18:59:26 -0700 | [diff] [blame] | 1219 | virtual                 ~OffloadThread() {}; | 
| Eric Laurent | e659ef4 | 2014-09-29 13:06:46 -0700 | [diff] [blame] | 1220 | virtual     void        flushHw_l(); | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1221 |  | 
|  | 1222 | protected: | 
|  | 1223 | // threadLoop snippets | 
|  | 1224 | virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove); | 
|  | 1225 | virtual     void        threadLoop_exit(); | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1226 |  | 
|  | 1227 | virtual     bool        waitingAsyncCallback(); | 
|  | 1228 | virtual     bool        waitingAsyncCallback_l(); | 
| Haynes Mathew George | 05317d2 | 2016-05-03 16:34:26 -0700 | [diff] [blame] | 1229 | virtual     void        invalidateTracks(audio_stream_type_t streamType); | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1230 |  | 
| Eric Laurent | de0613d | 2016-07-22 18:19:11 -0700 | [diff] [blame] | 1231 | virtual     bool        keepWakeLock() const { return (mKeepWakeLock || (mDrainSequence & 1)); } | 
| Eric Laurent | 6466797 | 2016-03-30 18:19:46 -0700 | [diff] [blame] | 1232 |  | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1233 | private: | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1234 | size_t      mPausedWriteLength;     // length in bytes of write interrupted by pause | 
|  | 1235 | size_t      mPausedBytesRemaining;  // bytes still waiting in mixbuffer after resume | 
| Eric Laurent | 6466797 | 2016-03-30 18:19:46 -0700 | [diff] [blame] | 1236 | bool        mKeepWakeLock;          // keep wake lock while waiting for write callback | 
| Andy Hung | f804475 | 2016-07-27 14:58:11 -0700 | [diff] [blame] | 1237 | uint64_t    mOffloadUnderrunPosition; // Current frame position for offloaded playback | 
|  | 1238 | // used and valid only during underrun.  ~0 if | 
|  | 1239 | // no underrun has occurred during playback and | 
|  | 1240 | // is not reset on standby. | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1241 | }; | 
|  | 1242 |  | 
|  | 1243 | class AsyncCallbackThread : public Thread { | 
|  | 1244 | public: | 
|  | 1245 |  | 
| Chih-Hung Hsieh | e964d4e | 2016-08-09 14:31:32 -0700 | [diff] [blame] | 1246 | explicit AsyncCallbackThread(const wp<PlaybackThread>& playbackThread); | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1247 |  | 
|  | 1248 | virtual             ~AsyncCallbackThread(); | 
|  | 1249 |  | 
|  | 1250 | // Thread virtuals | 
|  | 1251 | virtual bool        threadLoop(); | 
|  | 1252 |  | 
|  | 1253 | // RefBase | 
|  | 1254 | virtual void        onFirstRef(); | 
|  | 1255 |  | 
|  | 1256 | void        exit(); | 
| Eric Laurent | 3b4529e | 2013-09-05 18:09:19 -0700 | [diff] [blame] | 1257 | void        setWriteBlocked(uint32_t sequence); | 
|  | 1258 | void        resetWriteBlocked(); | 
|  | 1259 | void        setDraining(uint32_t sequence); | 
|  | 1260 | void        resetDraining(); | 
| Haynes Mathew George | 4527b9e | 2016-07-07 19:54:17 -0700 | [diff] [blame] | 1261 | void        setAsyncError(); | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1262 |  | 
|  | 1263 | private: | 
| Eric Laurent | 4de9559 | 2013-09-26 15:28:21 -0700 | [diff] [blame] | 1264 | const wp<PlaybackThread>   mPlaybackThread; | 
| Eric Laurent | 3b4529e | 2013-09-05 18:09:19 -0700 | [diff] [blame] | 1265 | // mWriteAckSequence corresponds to the last write sequence passed by the offload thread via | 
|  | 1266 | // setWriteBlocked(). The sequence is shifted one bit to the left and the lsb is used | 
|  | 1267 | // to indicate that the callback has been received via resetWriteBlocked() | 
| Eric Laurent | 4de9559 | 2013-09-26 15:28:21 -0700 | [diff] [blame] | 1268 | uint32_t                   mWriteAckSequence; | 
| Eric Laurent | 3b4529e | 2013-09-05 18:09:19 -0700 | [diff] [blame] | 1269 | // mDrainSequence corresponds to the last drain sequence passed by the offload thread via | 
|  | 1270 | // setDraining(). The sequence is shifted one bit to the left and the lsb is used | 
|  | 1271 | // to indicate that the callback has been received via resetDraining() | 
| Eric Laurent | 4de9559 | 2013-09-26 15:28:21 -0700 | [diff] [blame] | 1272 | uint32_t                   mDrainSequence; | 
|  | 1273 | Condition                  mWaitWorkCV; | 
|  | 1274 | Mutex                      mLock; | 
| Haynes Mathew George | 4527b9e | 2016-07-07 19:54:17 -0700 | [diff] [blame] | 1275 | bool                       mAsyncError; | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1276 | }; | 
|  | 1277 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1278 | class DuplicatingThread : public MixerThread { | 
|  | 1279 | public: | 
|  | 1280 | DuplicatingThread(const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread, | 
| Eric Laurent | 72e3f39 | 2015-05-20 14:43:50 -0700 | [diff] [blame] | 1281 | audio_io_handle_t id, bool systemReady); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1282 | virtual                 ~DuplicatingThread(); | 
|  | 1283 |  | 
|  | 1284 | // Thread virtuals | 
| Andy Hung | 1bc088a | 2018-02-09 15:57:31 -0800 | [diff] [blame] | 1285 | virtual     void        dumpInternals(int fd, const Vector<String16>& args) override; | 
|  | 1286 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1287 | void        addOutputTrack(MixerThread* thread); | 
|  | 1288 | void        removeOutputTrack(MixerThread* thread); | 
|  | 1289 | uint32_t    waitTimeMs() const { return mWaitTimeMs; } | 
| Kevin Rocard | 069c271 | 2018-03-29 19:09:14 -0700 | [diff] [blame] | 1290 |  | 
| Kevin Rocard | c86a7f7 | 2018-04-03 09:00:09 -0700 | [diff] [blame] | 1291 | void        sendMetadataToBackend_l( | 
|  | 1292 | const StreamOutHalInterface::SourceMetadata& metadata) override; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1293 | protected: | 
|  | 1294 | virtual     uint32_t    activeSleepTimeUs() const; | 
|  | 1295 |  | 
|  | 1296 | private: | 
|  | 1297 | bool        outputsReady(const SortedVector< sp<OutputTrack> > &outputTracks); | 
|  | 1298 | protected: | 
|  | 1299 | // threadLoop snippets | 
|  | 1300 | virtual     void        threadLoop_mix(); | 
|  | 1301 | virtual     void        threadLoop_sleepTime(); | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 1302 | virtual     ssize_t     threadLoop_write(); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1303 | virtual     void        threadLoop_standby(); | 
|  | 1304 | virtual     void        cacheParameters_l(); | 
|  | 1305 |  | 
|  | 1306 | private: | 
|  | 1307 | // called from threadLoop, addOutputTrack, removeOutputTrack | 
|  | 1308 | virtual     void        updateWaitTime_l(); | 
|  | 1309 | protected: | 
|  | 1310 | virtual     void        saveOutputTracks(); | 
|  | 1311 | virtual     void        clearOutputTracks(); | 
|  | 1312 | private: | 
|  | 1313 |  | 
|  | 1314 | uint32_t    mWaitTimeMs; | 
|  | 1315 | SortedVector < sp<OutputTrack> >  outputTracks; | 
|  | 1316 | SortedVector < sp<OutputTrack> >  mOutputTracks; | 
|  | 1317 | public: | 
|  | 1318 | virtual     bool        hasFastMixer() const { return false; } | 
|  | 1319 | }; | 
|  | 1320 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1321 | // record thread | 
| Glenn Kasten | 6dd62fb | 2013-12-05 16:35:58 -0800 | [diff] [blame] | 1322 | class RecordThread : public ThreadBase | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1323 | { | 
|  | 1324 | public: | 
|  | 1325 |  | 
| Glenn Kasten | 6dd62fb | 2013-12-05 16:35:58 -0800 | [diff] [blame] | 1326 | class RecordTrack; | 
| Andy Hung | 73c02e4 | 2015-03-29 01:13:58 -0700 | [diff] [blame] | 1327 |  | 
|  | 1328 | /* The ResamplerBufferProvider is used to retrieve recorded input data from the | 
|  | 1329 | * RecordThread.  It maintains local state on the relative position of the read | 
|  | 1330 | * position of the RecordTrack compared with the RecordThread. | 
|  | 1331 | */ | 
| Glenn Kasten | 6dd62fb | 2013-12-05 16:35:58 -0800 | [diff] [blame] | 1332 | class ResamplerBufferProvider : public AudioBufferProvider | 
| Glenn Kasten | 6dd62fb | 2013-12-05 16:35:58 -0800 | [diff] [blame] | 1333 | { | 
|  | 1334 | public: | 
| Chih-Hung Hsieh | e964d4e | 2016-08-09 14:31:32 -0700 | [diff] [blame] | 1335 | explicit ResamplerBufferProvider(RecordTrack* recordTrack) : | 
| Andy Hung | 73c02e4 | 2015-03-29 01:13:58 -0700 | [diff] [blame] | 1336 | mRecordTrack(recordTrack), | 
|  | 1337 | mRsmpInUnrel(0), mRsmpInFront(0) { } | 
| Glenn Kasten | 6dd62fb | 2013-12-05 16:35:58 -0800 | [diff] [blame] | 1338 | virtual ~ResamplerBufferProvider() { } | 
| Andy Hung | 73c02e4 | 2015-03-29 01:13:58 -0700 | [diff] [blame] | 1339 |  | 
|  | 1340 | // called to set the ResamplerBufferProvider to head of the RecordThread data buffer, | 
|  | 1341 | // skipping any previous data read from the hal. | 
|  | 1342 | virtual void reset(); | 
|  | 1343 |  | 
|  | 1344 | /* Synchronizes RecordTrack position with the RecordThread. | 
|  | 1345 | * Calculates available frames and handle overruns if the RecordThread | 
|  | 1346 | * has advanced faster than the ResamplerBufferProvider has retrieved data. | 
|  | 1347 | * TODO: why not do this for every getNextBuffer? | 
|  | 1348 | * | 
|  | 1349 | * Parameters | 
|  | 1350 | * framesAvailable:  pointer to optional output size_t to store record track | 
|  | 1351 | *                   frames available. | 
|  | 1352 | *      hasOverrun:  pointer to optional boolean, returns true if track has overrun. | 
|  | 1353 | */ | 
|  | 1354 |  | 
|  | 1355 | virtual void sync(size_t *framesAvailable = NULL, bool *hasOverrun = NULL); | 
|  | 1356 |  | 
| Glenn Kasten | 6dd62fb | 2013-12-05 16:35:58 -0800 | [diff] [blame] | 1357 | // AudioBufferProvider interface | 
| Glenn Kasten | d79072e | 2016-01-06 08:41:20 -0800 | [diff] [blame] | 1358 | virtual status_t    getNextBuffer(AudioBufferProvider::Buffer* buffer); | 
| Glenn Kasten | 6dd62fb | 2013-12-05 16:35:58 -0800 | [diff] [blame] | 1359 | virtual void        releaseBuffer(AudioBufferProvider::Buffer* buffer); | 
|  | 1360 | private: | 
|  | 1361 | RecordTrack * const mRecordTrack; | 
| Andy Hung | 73c02e4 | 2015-03-29 01:13:58 -0700 | [diff] [blame] | 1362 | size_t              mRsmpInUnrel;   // unreleased frames remaining from | 
|  | 1363 | // most recent getNextBuffer | 
|  | 1364 | // for debug only | 
|  | 1365 | int32_t             mRsmpInFront;   // next available frame | 
|  | 1366 | // rolling counter that is never cleared | 
| Glenn Kasten | 6dd62fb | 2013-12-05 16:35:58 -0800 | [diff] [blame] | 1367 | }; | 
|  | 1368 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1369 | #include "RecordTracks.h" | 
|  | 1370 |  | 
|  | 1371 | RecordThread(const sp<AudioFlinger>& audioFlinger, | 
|  | 1372 | AudioStreamIn *input, | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1373 | audio_io_handle_t id, | 
| Eric Laurent | d3922f7 | 2013-02-01 17:57:04 -0800 | [diff] [blame] | 1374 | audio_devices_t outDevice, | 
| Eric Laurent | 72e3f39 | 2015-05-20 14:43:50 -0700 | [diff] [blame] | 1375 | audio_devices_t inDevice, | 
|  | 1376 | bool systemReady | 
| Glenn Kasten | 46909e7 | 2013-02-26 09:20:22 -0800 | [diff] [blame] | 1377 | #ifdef TEE_SINK | 
|  | 1378 | , const sp<NBAIO_Sink>& teeSink | 
|  | 1379 | #endif | 
|  | 1380 | ); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1381 | virtual     ~RecordThread(); | 
|  | 1382 |  | 
|  | 1383 | // no addTrack_l ? | 
|  | 1384 | void        destroyTrack_l(const sp<RecordTrack>& track); | 
|  | 1385 | void        removeTrack_l(const sp<RecordTrack>& track); | 
|  | 1386 |  | 
|  | 1387 | void        dumpInternals(int fd, const Vector<String16>& args); | 
|  | 1388 | void        dumpTracks(int fd, const Vector<String16>& args); | 
|  | 1389 |  | 
|  | 1390 | // Thread virtuals | 
|  | 1391 | virtual bool        threadLoop(); | 
| Eric Laurent | 555530a | 2017-02-07 18:17:24 -0800 | [diff] [blame] | 1392 | virtual void        preExit(); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1393 |  | 
|  | 1394 | // RefBase | 
|  | 1395 | virtual void        onFirstRef(); | 
|  | 1396 |  | 
|  | 1397 | virtual status_t    initCheck() const { return (mInput == NULL) ? NO_INIT : NO_ERROR; } | 
| Glenn Kasten | e198c36 | 2013-08-13 09:13:36 -0700 | [diff] [blame] | 1398 |  | 
| Glenn Kasten | b880f5e | 2014-05-07 08:43:45 -0700 | [diff] [blame] | 1399 | virtual sp<MemoryDealer>    readOnlyHeap() const { return mReadOnlyHeap; } | 
|  | 1400 |  | 
| Glenn Kasten | 6dbb5e3 | 2014-05-13 10:38:42 -0700 | [diff] [blame] | 1401 | virtual sp<IMemory> pipeMemory() const { return mPipeMemory; } | 
|  | 1402 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1403 | sp<AudioFlinger::RecordThread::RecordTrack>  createRecordTrack_l( | 
|  | 1404 | const sp<AudioFlinger::Client>& client, | 
| Kevin Rocard | 1f564ac | 2018-03-29 13:53:10 -0700 | [diff] [blame] | 1405 | const audio_attributes_t& attr, | 
| Eric Laurent | f14db3c | 2017-12-08 14:20:36 -0800 | [diff] [blame] | 1406 | uint32_t *pSampleRate, | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1407 | audio_format_t format, | 
|  | 1408 | audio_channel_mask_t channelMask, | 
| Glenn Kasten | 74935e4 | 2013-12-19 08:56:45 -0800 | [diff] [blame] | 1409 | size_t *pFrameCount, | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 1410 | audio_session_t sessionId, | 
| Eric Laurent | f14db3c | 2017-12-08 14:20:36 -0800 | [diff] [blame] | 1411 | size_t *pNotificationFrameCount, | 
| Andy Hung | 1f12a8a | 2016-11-07 16:10:30 -0800 | [diff] [blame] | 1412 | uid_t uid, | 
| Eric Laurent | 0506778 | 2016-06-01 18:27:28 -0700 | [diff] [blame] | 1413 | audio_input_flags_t *flags, | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1414 | pid_t tid, | 
| Eric Laurent | 20b9ef0 | 2016-12-05 11:03:16 -0800 | [diff] [blame] | 1415 | status_t *status /*non-NULL*/, | 
|  | 1416 | audio_port_handle_t portId); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1417 |  | 
|  | 1418 | status_t    start(RecordTrack* recordTrack, | 
|  | 1419 | AudioSystem::sync_event_t event, | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 1420 | audio_session_t triggerSession); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1421 |  | 
|  | 1422 | // ask the thread to stop the specified track, and | 
|  | 1423 | // return true if the caller should then do it's part of the stopping process | 
| Glenn Kasten | a8356f6 | 2013-07-25 14:37:52 -0700 | [diff] [blame] | 1424 | bool        stop(RecordTrack* recordTrack); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1425 |  | 
|  | 1426 | void        dump(int fd, const Vector<String16>& args); | 
|  | 1427 | AudioStreamIn* clearInput(); | 
| Mikhail Naganov | 1dc9867 | 2016-08-18 17:50:29 -0700 | [diff] [blame] | 1428 | virtual sp<StreamHalInterface> stream() const; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1429 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1430 |  | 
| Eric Laurent | 1035194 | 2014-05-08 18:49:52 -0700 | [diff] [blame] | 1431 | virtual bool        checkForNewParameter_l(const String8& keyValuePair, | 
|  | 1432 | status_t& status); | 
|  | 1433 | virtual void        cacheParameters_l() {} | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1434 | virtual String8     getParameters(const String8& keys); | 
| Eric Laurent | 7c1ec5f | 2015-07-09 14:52:47 -0700 | [diff] [blame] | 1435 | virtual void        ioConfigChanged(audio_io_config_event event, pid_t pid = 0); | 
| Eric Laurent | 1c333e2 | 2014-05-20 10:48:17 -0700 | [diff] [blame] | 1436 | virtual status_t    createAudioPatch_l(const struct audio_patch *patch, | 
|  | 1437 | audio_patch_handle_t *handle); | 
|  | 1438 | virtual status_t    releaseAudioPatch_l(const audio_patch_handle_t handle); | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 1439 |  | 
| Mikhail Naganov | 444ecc3 | 2018-05-01 17:40:05 -0700 | [diff] [blame] | 1440 | void        addPatchTrack(const sp<PatchRecord>& record); | 
|  | 1441 | void        deletePatchTrack(const sp<PatchRecord>& record); | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 1442 |  | 
| Glenn Kasten | deca2ae | 2014-02-07 10:25:56 -0800 | [diff] [blame] | 1443 | void        readInputParameters_l(); | 
| Glenn Kasten | 5f972c0 | 2014-01-13 09:59:31 -0800 | [diff] [blame] | 1444 | virtual uint32_t    getInputFramesLost(); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1445 |  | 
|  | 1446 | virtual status_t addEffectChain_l(const sp<EffectChain>& chain); | 
|  | 1447 | virtual size_t removeEffectChain_l(const sp<EffectChain>& chain); | 
| Eric Laurent | 4c41506 | 2016-06-17 16:14:16 -0700 | [diff] [blame] | 1448 | virtual uint32_t hasAudioSession_l(audio_session_t sessionId) const; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1449 |  | 
|  | 1450 | // Return the set of unique session IDs across all tracks. | 
|  | 1451 | // The keys are the session IDs, and the associated values are meaningless. | 
|  | 1452 | // FIXME replace by Set [and implement Bag/Multiset for other uses]. | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 1453 | KeyedVector<audio_session_t, bool> sessionIds() const; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1454 |  | 
|  | 1455 | virtual status_t setSyncEvent(const sp<SyncEvent>& event); | 
|  | 1456 | virtual bool     isValidSyncEvent(const sp<SyncEvent>& event) const; | 
|  | 1457 |  | 
|  | 1458 | static void syncStartEventCallback(const wp<SyncEvent>& event); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1459 |  | 
| Glenn Kasten | 9b58f63 | 2013-07-16 11:37:48 -0700 | [diff] [blame] | 1460 | virtual size_t      frameCount() const { return mFrameCount; } | 
| Glenn Kasten | 6dbb5e3 | 2014-05-13 10:38:42 -0700 | [diff] [blame] | 1461 | bool        hasFastCapture() const { return mFastCapture != 0; } | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 1462 | virtual void        getAudioPortConfig(struct audio_port_config *config); | 
| Glenn Kasten | 9b58f63 | 2013-07-16 11:37:48 -0700 | [diff] [blame] | 1463 |  | 
| Eric Laurent | 4c41506 | 2016-06-17 16:14:16 -0700 | [diff] [blame] | 1464 | virtual status_t    checkEffectCompatibility_l(const effect_descriptor_t *desc, | 
|  | 1465 | audio_session_t sessionId); | 
|  | 1466 |  | 
| Andy Hung | dae2770 | 2016-10-31 14:01:16 -0700 | [diff] [blame] | 1467 | virtual void        acquireWakeLock_l() { | 
|  | 1468 | ThreadBase::acquireWakeLock_l(); | 
|  | 1469 | mActiveTracks.updatePowerState(this, true /* force */); | 
|  | 1470 | } | 
| Andy Hung | 293558a | 2017-03-21 12:19:20 -0700 | [diff] [blame] | 1471 | virtual bool        isOutput() const override { return false; } | 
| Andy Hung | dae2770 | 2016-10-31 14:01:16 -0700 | [diff] [blame] | 1472 |  | 
| Eric Laurent | d8365c5 | 2017-07-16 15:27:05 -0700 | [diff] [blame] | 1473 | void        checkBtNrec(); | 
|  | 1474 |  | 
| Svet Ganov | f4ddfef | 2018-01-16 07:37:58 -0800 | [diff] [blame] | 1475 | // Sets the UID records silence | 
|  | 1476 | void        setRecordSilenced(uid_t uid, bool silenced); | 
|  | 1477 |  | 
| jiabin | 653cc0a | 2018-01-17 17:54:10 -0800 | [diff] [blame] | 1478 | status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones); | 
|  | 1479 |  | 
| Kevin Rocard | 069c271 | 2018-03-29 19:09:14 -0700 | [diff] [blame] | 1480 | void        updateMetadata_l() override; | 
|  | 1481 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1482 | private: | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1483 | // Enter standby if not already in standby, and set mStandby flag | 
| Glenn Kasten | 93e471f | 2013-08-19 08:40:07 -0700 | [diff] [blame] | 1484 | void    standbyIfNotAlreadyInStandby(); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1485 |  | 
|  | 1486 | // Call the HAL standby method unconditionally, and don't change mStandby flag | 
| Glenn Kasten | e198c36 | 2013-08-13 09:13:36 -0700 | [diff] [blame] | 1487 | void    inputStandBy(); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1488 |  | 
| Eric Laurent | d8365c5 | 2017-07-16 15:27:05 -0700 | [diff] [blame] | 1489 | void    checkBtNrec_l(); | 
|  | 1490 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1491 | AudioStreamIn                       *mInput; | 
|  | 1492 | SortedVector < sp<RecordTrack> >    mTracks; | 
| Glenn Kasten | 2b80640 | 2013-11-20 16:37:38 -0800 | [diff] [blame] | 1493 | // mActiveTracks has dual roles:  it indicates the current active track(s), and | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1494 | // is used together with mStartStopCond to indicate start()/stop() progress | 
| Andy Hung | dae2770 | 2016-10-31 14:01:16 -0700 | [diff] [blame] | 1495 | ActiveTracks<RecordTrack>           mActiveTracks; | 
|  | 1496 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1497 | Condition                           mStartStopCond; | 
| Glenn Kasten | 9b58f63 | 2013-07-16 11:37:48 -0700 | [diff] [blame] | 1498 |  | 
| Glenn Kasten | 8594843 | 2013-08-19 12:09:05 -0700 | [diff] [blame] | 1499 | // resampler converts input at HAL Hz to output at AudioRecord client Hz | 
| Glenn Kasten | 1b29184 | 2016-07-18 14:55:21 -0700 | [diff] [blame] | 1500 | void                               *mRsmpInBuffer;  // size = mRsmpInFramesOA | 
| Glenn Kasten | 8594843 | 2013-08-19 12:09:05 -0700 | [diff] [blame] | 1501 | size_t                              mRsmpInFrames;  // size of resampler input in frames | 
|  | 1502 | size_t                              mRsmpInFramesP2;// size rounded up to a power-of-2 | 
| Glenn Kasten | 1b29184 | 2016-07-18 14:55:21 -0700 | [diff] [blame] | 1503 | size_t                              mRsmpInFramesOA;// mRsmpInFramesP2 + over-allocation | 
| Glenn Kasten | 6dd62fb | 2013-12-05 16:35:58 -0800 | [diff] [blame] | 1504 |  | 
|  | 1505 | // rolling index that is never cleared | 
| Glenn Kasten | 8594843 | 2013-08-19 12:09:05 -0700 | [diff] [blame] | 1506 | int32_t                             mRsmpInRear;    // last filled frame + 1 | 
| Glenn Kasten | 8594843 | 2013-08-19 12:09:05 -0700 | [diff] [blame] | 1507 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1508 | // For dumpsys | 
|  | 1509 | const sp<NBAIO_Sink>                mTeeSink; | 
| Glenn Kasten | b880f5e | 2014-05-07 08:43:45 -0700 | [diff] [blame] | 1510 |  | 
|  | 1511 | const sp<MemoryDealer>              mReadOnlyHeap; | 
| Glenn Kasten | 6dbb5e3 | 2014-05-13 10:38:42 -0700 | [diff] [blame] | 1512 |  | 
|  | 1513 | // one-time initialization, no locks required | 
| Glenn Kasten | b187de1 | 2014-12-30 08:18:15 -0800 | [diff] [blame] | 1514 | sp<FastCapture>                     mFastCapture;   // non-0 if there is also | 
|  | 1515 | // a fast capture | 
| Eric Laurent | 72e3f39 | 2015-05-20 14:43:50 -0700 | [diff] [blame] | 1516 |  | 
| Glenn Kasten | 6dbb5e3 | 2014-05-13 10:38:42 -0700 | [diff] [blame] | 1517 | // FIXME audio watchdog thread | 
|  | 1518 |  | 
|  | 1519 | // contents are not guaranteed to be consistent, no locks required | 
|  | 1520 | FastCaptureDumpState                mFastCaptureDumpState; | 
|  | 1521 | #ifdef STATE_QUEUE_DUMP | 
|  | 1522 | // FIXME StateQueue observer and mutator dump fields | 
|  | 1523 | #endif | 
|  | 1524 | // FIXME audio watchdog dump | 
|  | 1525 |  | 
|  | 1526 | // accessible only within the threadLoop(), no locks required | 
|  | 1527 | //          mFastCapture->sq()      // for mutating and pushing state | 
|  | 1528 | int32_t     mFastCaptureFutex;      // for cold idle | 
|  | 1529 |  | 
|  | 1530 | // The HAL input source is treated as non-blocking, | 
|  | 1531 | // but current implementation is blocking | 
|  | 1532 | sp<NBAIO_Source>                    mInputSource; | 
|  | 1533 | // The source for the normal capture thread to read from: mInputSource or mPipeSource | 
|  | 1534 | sp<NBAIO_Source>                    mNormalSource; | 
|  | 1535 | // If a fast capture is present, the non-blocking pipe sink written to by fast capture, | 
|  | 1536 | // otherwise clear | 
|  | 1537 | sp<NBAIO_Sink>                      mPipeSink; | 
|  | 1538 | // If a fast capture is present, the non-blocking pipe source read by normal thread, | 
|  | 1539 | // otherwise clear | 
|  | 1540 | sp<NBAIO_Source>                    mPipeSource; | 
|  | 1541 | // Depth of pipe from fast capture to normal thread and fast clients, always power of 2 | 
|  | 1542 | size_t                              mPipeFramesP2; | 
|  | 1543 | // If a fast capture is present, the Pipe as IMemory, otherwise clear | 
|  | 1544 | sp<IMemory>                         mPipeMemory; | 
|  | 1545 |  | 
| Sanna Catherine de Treville Wager | 2a6a945 | 2017-07-28 11:02:01 -0700 | [diff] [blame] | 1546 | // TODO: add comment and adjust size as needed | 
| Glenn Kasten | 6dbb5e3 | 2014-05-13 10:38:42 -0700 | [diff] [blame] | 1547 | static const size_t                 kFastCaptureLogSize = 4 * 1024; | 
|  | 1548 | sp<NBLog::Writer>                   mFastCaptureNBLogWriter; | 
|  | 1549 |  | 
|  | 1550 | bool                                mFastTrackAvail;    // true if fast track available | 
| Eric Laurent | d8365c5 | 2017-07-16 15:27:05 -0700 | [diff] [blame] | 1551 | // common state to all record threads | 
|  | 1552 | std::atomic_bool                    mBtNrecSuspended; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 1553 | }; | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1554 |  | 
|  | 1555 | class MmapThread : public ThreadBase | 
|  | 1556 | { | 
|  | 1557 | public: | 
|  | 1558 |  | 
|  | 1559 | #include "MmapTracks.h" | 
|  | 1560 |  | 
|  | 1561 | MmapThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id, | 
|  | 1562 | AudioHwDevice *hwDev, sp<StreamHalInterface> stream, | 
|  | 1563 | audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady); | 
|  | 1564 | virtual     ~MmapThread(); | 
|  | 1565 |  | 
|  | 1566 | virtual     void        configure(const audio_attributes_t *attr, | 
|  | 1567 | audio_stream_type_t streamType, | 
|  | 1568 | audio_session_t sessionId, | 
|  | 1569 | const sp<MmapStreamCallback>& callback, | 
| Eric Laurent | 7aa0ccb | 2017-08-28 11:12:52 -0700 | [diff] [blame] | 1570 | audio_port_handle_t deviceId, | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1571 | audio_port_handle_t portId); | 
|  | 1572 |  | 
|  | 1573 | void        disconnect(); | 
|  | 1574 |  | 
|  | 1575 | // MmapStreamInterface | 
|  | 1576 | status_t createMmapBuffer(int32_t minSizeFrames, | 
|  | 1577 | struct audio_mmap_buffer_info *info); | 
|  | 1578 | status_t getMmapPosition(struct audio_mmap_position *position); | 
| Eric Laurent | a54f128 | 2017-07-01 19:39:32 -0700 | [diff] [blame] | 1579 | status_t start(const AudioClient& client, audio_port_handle_t *handle); | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1580 | status_t stop(audio_port_handle_t handle); | 
| Eric Laurent | 18b5701 | 2017-02-13 16:23:52 -0800 | [diff] [blame] | 1581 | status_t standby(); | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1582 |  | 
|  | 1583 | // RefBase | 
|  | 1584 | virtual     void        onFirstRef(); | 
|  | 1585 |  | 
|  | 1586 | // Thread virtuals | 
|  | 1587 | virtual     bool        threadLoop(); | 
|  | 1588 |  | 
|  | 1589 | virtual     void        threadLoop_exit(); | 
|  | 1590 | virtual     void        threadLoop_standby(); | 
| Eric Laurent | 18b5701 | 2017-02-13 16:23:52 -0800 | [diff] [blame] | 1591 | virtual     bool        shouldStandby_l() { return false; } | 
| Eric Laurent | 331679c | 2018-04-16 17:03:16 -0700 | [diff] [blame] | 1592 | virtual     status_t    exitStandby(); | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1593 |  | 
|  | 1594 | virtual     status_t    initCheck() const { return (mHalStream == 0) ? NO_INIT : NO_ERROR; } | 
|  | 1595 | virtual     size_t      frameCount() const { return mFrameCount; } | 
|  | 1596 | virtual     bool        checkForNewParameter_l(const String8& keyValuePair, | 
|  | 1597 | status_t& status); | 
|  | 1598 | virtual     String8     getParameters(const String8& keys); | 
|  | 1599 | virtual     void        ioConfigChanged(audio_io_config_event event, pid_t pid = 0); | 
|  | 1600 | void        readHalParameters_l(); | 
|  | 1601 | virtual     void        cacheParameters_l() {} | 
|  | 1602 | virtual     status_t    createAudioPatch_l(const struct audio_patch *patch, | 
|  | 1603 | audio_patch_handle_t *handle); | 
|  | 1604 | virtual     status_t    releaseAudioPatch_l(const audio_patch_handle_t handle); | 
|  | 1605 | virtual     void        getAudioPortConfig(struct audio_port_config *config); | 
|  | 1606 |  | 
|  | 1607 | virtual     sp<StreamHalInterface> stream() const { return mHalStream; } | 
|  | 1608 | virtual     status_t    addEffectChain_l(const sp<EffectChain>& chain); | 
|  | 1609 | virtual     size_t      removeEffectChain_l(const sp<EffectChain>& chain); | 
|  | 1610 | virtual     status_t    checkEffectCompatibility_l(const effect_descriptor_t *desc, | 
|  | 1611 | audio_session_t sessionId); | 
|  | 1612 |  | 
|  | 1613 | virtual     uint32_t    hasAudioSession_l(audio_session_t sessionId) const; | 
|  | 1614 | virtual     status_t    setSyncEvent(const sp<SyncEvent>& event); | 
|  | 1615 | virtual     bool        isValidSyncEvent(const sp<SyncEvent>& event) const; | 
|  | 1616 |  | 
|  | 1617 | virtual     void        checkSilentMode_l() {} | 
|  | 1618 | virtual     void        processVolume_l() {} | 
|  | 1619 | void        checkInvalidTracks_l(); | 
|  | 1620 |  | 
|  | 1621 | virtual     audio_stream_type_t streamType() { return AUDIO_STREAM_DEFAULT; } | 
|  | 1622 |  | 
|  | 1623 | virtual     void        invalidateTracks(audio_stream_type_t streamType __unused) {} | 
|  | 1624 |  | 
| Eric Laurent | 331679c | 2018-04-16 17:03:16 -0700 | [diff] [blame] | 1625 | // Sets the UID records silence | 
|  | 1626 | virtual     void        setRecordSilenced(uid_t uid __unused, bool silenced __unused) {} | 
|  | 1627 |  | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1628 | void        dump(int fd, const Vector<String16>& args); | 
|  | 1629 | virtual     void        dumpInternals(int fd, const Vector<String16>& args); | 
|  | 1630 | void        dumpTracks(int fd, const Vector<String16>& args); | 
|  | 1631 |  | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1632 | protected: | 
|  | 1633 |  | 
|  | 1634 | audio_attributes_t      mAttr; | 
|  | 1635 | audio_session_t         mSessionId; | 
| Eric Laurent | 7aa0ccb | 2017-08-28 11:12:52 -0700 | [diff] [blame] | 1636 | audio_port_handle_t     mDeviceId; | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1637 | audio_port_handle_t     mPortId; | 
|  | 1638 |  | 
| Phil Burk | 7f6b40d | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 1639 | wp<MmapStreamCallback>  mCallback; | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1640 | sp<StreamHalInterface>  mHalStream; | 
|  | 1641 | sp<DeviceHalInterface>  mHalDevice; | 
|  | 1642 | AudioHwDevice* const    mAudioHwDev; | 
|  | 1643 | ActiveTracks<MmapTrack> mActiveTracks; | 
| Eric Laurent | 67f9729 | 2018-04-20 18:05:41 -0700 | [diff] [blame] | 1644 | float                   mHalVolFloat; | 
| Eric Laurent | 331679c | 2018-04-16 17:03:16 -0700 | [diff] [blame] | 1645 |  | 
|  | 1646 | int32_t                 mNoCallbackWarningCount; | 
|  | 1647 | static     constexpr int32_t       kMaxNoCallbackWarnings = 5; | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1648 | }; | 
|  | 1649 |  | 
|  | 1650 | class MmapPlaybackThread : public MmapThread, public VolumeInterface | 
|  | 1651 | { | 
|  | 1652 |  | 
|  | 1653 | public: | 
|  | 1654 | MmapPlaybackThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id, | 
|  | 1655 | AudioHwDevice *hwDev, AudioStreamOut *output, | 
|  | 1656 | audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady); | 
|  | 1657 | virtual     ~MmapPlaybackThread() {} | 
|  | 1658 |  | 
|  | 1659 | virtual     void        configure(const audio_attributes_t *attr, | 
|  | 1660 | audio_stream_type_t streamType, | 
|  | 1661 | audio_session_t sessionId, | 
|  | 1662 | const sp<MmapStreamCallback>& callback, | 
| Eric Laurent | 7aa0ccb | 2017-08-28 11:12:52 -0700 | [diff] [blame] | 1663 | audio_port_handle_t deviceId, | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1664 | audio_port_handle_t portId); | 
|  | 1665 |  | 
|  | 1666 | AudioStreamOut* clearOutput(); | 
|  | 1667 |  | 
|  | 1668 | // VolumeInterface | 
|  | 1669 | virtual     void        setMasterVolume(float value); | 
|  | 1670 | virtual     void        setMasterMute(bool muted); | 
|  | 1671 | virtual     void        setStreamVolume(audio_stream_type_t stream, float value); | 
|  | 1672 | virtual     void        setStreamMute(audio_stream_type_t stream, bool muted); | 
|  | 1673 | virtual     float       streamVolume(audio_stream_type_t stream) const; | 
|  | 1674 |  | 
|  | 1675 | void        setMasterMute_l(bool muted) { mMasterMute = muted; } | 
|  | 1676 |  | 
|  | 1677 | virtual     void        invalidateTracks(audio_stream_type_t streamType); | 
|  | 1678 |  | 
|  | 1679 | virtual     audio_stream_type_t streamType() { return mStreamType; } | 
|  | 1680 | virtual     void        checkSilentMode_l(); | 
| Eric Laurent | 331679c | 2018-04-16 17:03:16 -0700 | [diff] [blame] | 1681 | void        processVolume_l() override; | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1682 |  | 
|  | 1683 | virtual     void        dumpInternals(int fd, const Vector<String16>& args); | 
|  | 1684 |  | 
| Andy Hung | 293558a | 2017-03-21 12:19:20 -0700 | [diff] [blame] | 1685 | virtual     bool        isOutput() const override { return true; } | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1686 |  | 
| Kevin Rocard | 069c271 | 2018-03-29 19:09:14 -0700 | [diff] [blame] | 1687 | void        updateMetadata_l() override; | 
|  | 1688 |  | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1689 | protected: | 
|  | 1690 |  | 
|  | 1691 | audio_stream_type_t         mStreamType; | 
|  | 1692 | float                       mMasterVolume; | 
|  | 1693 | float                       mStreamVolume; | 
|  | 1694 | bool                        mMasterMute; | 
|  | 1695 | bool                        mStreamMute; | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1696 | AudioStreamOut*             mOutput; | 
|  | 1697 | }; | 
|  | 1698 |  | 
|  | 1699 | class MmapCaptureThread : public MmapThread | 
|  | 1700 | { | 
|  | 1701 |  | 
|  | 1702 | public: | 
|  | 1703 | MmapCaptureThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id, | 
|  | 1704 | AudioHwDevice *hwDev, AudioStreamIn *input, | 
|  | 1705 | audio_devices_t outDevice, audio_devices_t inDevice, bool systemReady); | 
|  | 1706 | virtual     ~MmapCaptureThread() {} | 
|  | 1707 |  | 
|  | 1708 | AudioStreamIn* clearInput(); | 
|  | 1709 |  | 
| Eric Laurent | 331679c | 2018-04-16 17:03:16 -0700 | [diff] [blame] | 1710 | status_t       exitStandby() override; | 
| Andy Hung | 293558a | 2017-03-21 12:19:20 -0700 | [diff] [blame] | 1711 | virtual     bool           isOutput() const override { return false; } | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1712 |  | 
| Kevin Rocard | 069c271 | 2018-03-29 19:09:14 -0700 | [diff] [blame] | 1713 | void           updateMetadata_l() override; | 
| Eric Laurent | 331679c | 2018-04-16 17:03:16 -0700 | [diff] [blame] | 1714 | void           processVolume_l() override; | 
|  | 1715 | void           setRecordSilenced(uid_t uid, bool silenced) override; | 
| Kevin Rocard | 069c271 | 2018-03-29 19:09:14 -0700 | [diff] [blame] | 1716 |  | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 1717 | protected: | 
|  | 1718 |  | 
|  | 1719 | AudioStreamIn*  mInput; | 
|  | 1720 | }; |