| 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 | // base for record and playback | 
 | 23 | class TrackBase : public ExtendedAudioBufferProvider, public RefBase { | 
 | 24 |  | 
 | 25 | public: | 
 | 26 |     enum track_state { | 
 | 27 |         IDLE, | 
| Andy Hung | ce68540 | 2018-10-05 17:23:27 -0700 | [diff] [blame] | 28 |         FLUSHED,        // for PlaybackTracks only | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 29 |         STOPPED, | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 30 |         // next 2 states are currently used for fast tracks | 
 | 31 |         // and offloaded tracks only | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 32 |         STOPPING_1,     // waiting for first underrun | 
 | 33 |         STOPPING_2,     // waiting for presentation complete | 
| Andy Hung | ce68540 | 2018-10-05 17:23:27 -0700 | [diff] [blame] | 34 |         RESUMING,       // for PlaybackTracks only | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 35 |         ACTIVE, | 
 | 36 |         PAUSING, | 
| Glenn Kasten | 6dd62fb | 2013-12-05 16:35:58 -0800 | [diff] [blame] | 37 |         PAUSED, | 
 | 38 |         STARTING_1,     // for RecordTrack only | 
 | 39 |         STARTING_2,     // for RecordTrack only | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 40 |     }; | 
 | 41 |  | 
| Glenn Kasten | 6181ffd | 2014-05-13 10:41:52 -0700 | [diff] [blame] | 42 |     // where to allocate the data buffer | 
 | 43 |     enum alloc_type { | 
 | 44 |         ALLOC_CBLK,     // allocate immediately after control block | 
 | 45 |         ALLOC_READONLY, // allocate from a separate read-only heap per thread | 
 | 46 |         ALLOC_PIPE,     // do not allocate; use the pipe buffer | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 47 |         ALLOC_LOCAL,    // allocate a local buffer | 
 | 48 |         ALLOC_NONE,     // do not allocate:use the buffer passed to TrackBase constructor | 
 | 49 |     }; | 
 | 50 |  | 
 | 51 |     enum track_type { | 
 | 52 |         TYPE_DEFAULT, | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 53 |         TYPE_OUTPUT, | 
 | 54 |         TYPE_PATCH, | 
| Glenn Kasten | 6181ffd | 2014-05-13 10:41:52 -0700 | [diff] [blame] | 55 |     }; | 
 | 56 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 57 |                         TrackBase(ThreadBase *thread, | 
 | 58 |                                 const sp<Client>& client, | 
| Kevin Rocard | 1f564ac | 2018-03-29 13:53:10 -0700 | [diff] [blame] | 59 |                                 const audio_attributes_t& mAttr, | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 60 |                                 uint32_t sampleRate, | 
 | 61 |                                 audio_format_t format, | 
 | 62 |                                 audio_channel_mask_t channelMask, | 
 | 63 |                                 size_t frameCount, | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 64 |                                 void *buffer, | 
| Andy Hung | 8fe6803 | 2017-06-05 16:17:51 -0700 | [diff] [blame] | 65 |                                 size_t bufferSize, | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 66 |                                 audio_session_t sessionId, | 
| Eric Laurent | 09f1ed2 | 2019-04-24 17:45:17 -0700 | [diff] [blame] | 67 |                                 pid_t creatorPid, | 
| Andy Hung | 1f12a8a | 2016-11-07 16:10:30 -0800 | [diff] [blame] | 68 |                                 uid_t uid, | 
| Glenn Kasten | d776ac6 | 2014-05-07 09:16:09 -0700 | [diff] [blame] | 69 |                                 bool isOut, | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 70 |                                 alloc_type alloc = ALLOC_CBLK, | 
| Eric Laurent | 20b9ef0 | 2016-12-05 11:03:16 -0800 | [diff] [blame] | 71 |                                 track_type type = TYPE_DEFAULT, | 
| Andy Hung | b68f5eb | 2019-12-03 16:49:17 -0800 | [diff] [blame] | 72 |                                 audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE, | 
 | 73 |                                 std::string metricsId = {}); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 74 |     virtual             ~TrackBase(); | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 75 |     virtual status_t    initCheck() const; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 76 |  | 
 | 77 |     virtual status_t    start(AudioSystem::sync_event_t event, | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 78 |                              audio_session_t triggerSession) = 0; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 79 |     virtual void        stop() = 0; | 
 | 80 |             sp<IMemory> getCblk() const { return mCblkMemory; } | 
 | 81 |             audio_track_cblk_t* cblk() const { return mCblk; } | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 82 |             audio_session_t sessionId() const { return mSessionId; } | 
| Andy Hung | 1f12a8a | 2016-11-07 16:10:30 -0800 | [diff] [blame] | 83 |             uid_t       uid() const { return mUid; } | 
| Eric Laurent | 09f1ed2 | 2019-04-24 17:45:17 -0700 | [diff] [blame] | 84 |             pid_t       creatorPid() const { return mCreatorPid; } | 
 | 85 |  | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 86 |             audio_port_handle_t portId() const { return mPortId; } | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 87 |     virtual status_t    setSyncEvent(const sp<SyncEvent>& event); | 
 | 88 |  | 
| Glenn Kasten | d776ac6 | 2014-05-07 09:16:09 -0700 | [diff] [blame] | 89 |             sp<IMemory> getBuffers() const { return mBufferMemory; } | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 90 |             void*       buffer() const { return mBuffer; } | 
| Andy Hung | 8fe6803 | 2017-06-05 16:17:51 -0700 | [diff] [blame] | 91 |             size_t      bufferSize() const { return mBufferSize; } | 
| Eric Laurent | 0506778 | 2016-06-01 18:27:28 -0700 | [diff] [blame] | 92 |     virtual bool        isFastTrack() const = 0; | 
| Mikhail Naganov | 7c6ae98 | 2018-06-14 12:33:38 -0700 | [diff] [blame] | 93 |     virtual bool        isDirect() const = 0; | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 94 |             bool        isOutputTrack() const { return (mType == TYPE_OUTPUT); } | 
 | 95 |             bool        isPatchTrack() const { return (mType == TYPE_PATCH); } | 
 | 96 |             bool        isExternalTrack() const { return !isOutputTrack() && !isPatchTrack(); } | 
| Glenn Kasten | d776ac6 | 2014-05-07 09:16:09 -0700 | [diff] [blame] | 97 |  | 
| Andy Hung | b68f5eb | 2019-12-03 16:49:17 -0800 | [diff] [blame] | 98 |     virtual void        invalidate() { | 
 | 99 |                             if (mIsInvalid) return; | 
| Andy Hung | c2b11cb | 2020-04-22 09:04:01 -0700 | [diff] [blame] | 100 |                             mTrackMetrics.logInvalidate(); | 
| Andy Hung | b68f5eb | 2019-12-03 16:49:17 -0800 | [diff] [blame] | 101 |                             mIsInvalid = true; | 
 | 102 |                         } | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 103 |             bool        isInvalid() const { return mIsInvalid; } | 
 | 104 |  | 
| Andy Hung | c3d62f9 | 2019-03-14 13:38:51 -0700 | [diff] [blame] | 105 |             void        terminate() { mTerminated = true; } | 
 | 106 |             bool        isTerminated() const { return mTerminated; } | 
 | 107 |  | 
| Kevin Rocard | 069c271 | 2018-03-29 19:09:14 -0700 | [diff] [blame] | 108 |     audio_attributes_t  attributes() const { return mAttr; } | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 109 |  | 
| Andy Hung | 8946a28 | 2018-04-19 20:04:56 -0700 | [diff] [blame] | 110 | #ifdef TEE_SINK | 
 | 111 |            void         dumpTee(int fd, const std::string &reason) const { | 
 | 112 |                                 mTee.dump(fd, reason); | 
 | 113 |                         } | 
 | 114 | #endif | 
 | 115 |  | 
| Andy Hung | cef2daa | 2018-06-01 15:31:49 -0700 | [diff] [blame] | 116 |             /** returns the buffer contents size converted to time in milliseconds | 
 | 117 |              * for PCM Playback or Record streaming tracks. The return value is zero for | 
 | 118 |              * PCM static tracks and not defined for non-PCM tracks. | 
 | 119 |              * | 
 | 120 |              * This may be called without the thread lock. | 
 | 121 |              */ | 
 | 122 |     virtual double      bufferLatencyMs() const { | 
 | 123 |                             return mServerProxy->framesReadySafe() * 1000 / sampleRate(); | 
 | 124 |                         } | 
 | 125 |  | 
 | 126 |             /** returns whether the track supports server latency computation. | 
 | 127 |              * This is set in the constructor and constant throughout the track lifetime. | 
 | 128 |              */ | 
 | 129 |  | 
 | 130 |             bool        isServerLatencySupported() const { return mServerLatencySupported; } | 
 | 131 |  | 
 | 132 |             /** computes the server latency for PCM Playback or Record track | 
 | 133 |              * to the device sink/source.  This is the time for the next frame in the track buffer | 
 | 134 |              * written or read from the server thread to the device source or sink. | 
 | 135 |              * | 
 | 136 |              * This may be called without the thread lock, but latencyMs and fromTrack | 
 | 137 |              * may be not be synchronized. For example PatchPanel may not obtain the | 
 | 138 |              * thread lock before calling. | 
 | 139 |              * | 
 | 140 |              * \param latencyMs on success is set to the latency in milliseconds of the | 
 | 141 |              *        next frame written/read by the server thread to/from the track buffer | 
 | 142 |              *        from the device source/sink. | 
 | 143 |              * \param fromTrack on success is set to true if latency was computed directly | 
 | 144 |              *        from the track timestamp; otherwise set to false if latency was | 
 | 145 |              *        estimated from the server timestamp. | 
 | 146 |              *        fromTrack may be nullptr or omitted if not required. | 
 | 147 |              * | 
 | 148 |              * \returns OK or INVALID_OPERATION on failure. | 
 | 149 |              */ | 
 | 150 |             status_t    getServerLatencyMs(double *latencyMs, bool *fromTrack = nullptr) const { | 
 | 151 |                             if (!isServerLatencySupported()) { | 
 | 152 |                                 return INVALID_OPERATION; | 
 | 153 |                             } | 
 | 154 |  | 
 | 155 |                             // if no thread lock is acquired, these atomics are not | 
 | 156 |                             // synchronized with each other, considered a benign race. | 
 | 157 |  | 
 | 158 |                             const double serverLatencyMs = mServerLatencyMs.load(); | 
 | 159 |                             if (serverLatencyMs == 0.) { | 
 | 160 |                                 return INVALID_OPERATION; | 
 | 161 |                             } | 
 | 162 |                             if (fromTrack != nullptr) { | 
 | 163 |                                 *fromTrack = mServerLatencyFromTrack.load(); | 
 | 164 |                             } | 
 | 165 |                             *latencyMs = serverLatencyMs; | 
 | 166 |                             return OK; | 
 | 167 |                         } | 
 | 168 |  | 
 | 169 |             /** computes the total client latency for PCM Playback or Record tracks | 
 | 170 |              * for the next client app access to the device sink/source; i.e. the | 
 | 171 |              * server latency plus the buffer latency. | 
 | 172 |              * | 
 | 173 |              * This may be called without the thread lock, but latencyMs and fromTrack | 
 | 174 |              * may be not be synchronized. For example PatchPanel may not obtain the | 
 | 175 |              * thread lock before calling. | 
 | 176 |              * | 
 | 177 |              * \param latencyMs on success is set to the latency in milliseconds of the | 
 | 178 |              *        next frame written/read by the client app to/from the track buffer | 
 | 179 |              *        from the device sink/source. | 
 | 180 |              * \param fromTrack on success is set to true if latency was computed directly | 
 | 181 |              *        from the track timestamp; otherwise set to false if latency was | 
 | 182 |              *        estimated from the server timestamp. | 
 | 183 |              *        fromTrack may be nullptr or omitted if not required. | 
 | 184 |              * | 
 | 185 |              * \returns OK or INVALID_OPERATION on failure. | 
 | 186 |              */ | 
 | 187 |             status_t    getTrackLatencyMs(double *latencyMs, bool *fromTrack = nullptr) const { | 
 | 188 |                             double serverLatencyMs; | 
 | 189 |                             status_t status = getServerLatencyMs(&serverLatencyMs, fromTrack); | 
 | 190 |                             if (status == OK) { | 
 | 191 |                                 *latencyMs = serverLatencyMs + bufferLatencyMs(); | 
 | 192 |                             } | 
 | 193 |                             return status; | 
 | 194 |                         } | 
 | 195 |  | 
| Andy Hung | 3028256 | 2018-08-08 18:27:03 -0700 | [diff] [blame] | 196 |            // TODO: Consider making this external. | 
 | 197 |            struct FrameTime { | 
 | 198 |                int64_t frames; | 
 | 199 |                int64_t timeNs; | 
 | 200 |            }; | 
 | 201 |  | 
 | 202 |            // KernelFrameTime is updated per "mix" period even for non-pcm tracks. | 
 | 203 |            void         getKernelFrameTime(FrameTime *ft) const { | 
 | 204 |                            *ft = mKernelFrameTime.load(); | 
 | 205 |                         } | 
 | 206 |  | 
 | 207 |            audio_format_t format() const { return mFormat; } | 
| Andy Hung | c069138 | 2018-09-12 18:01:57 -0700 | [diff] [blame] | 208 |            int id() const { return mId; } | 
| Andy Hung | 3028256 | 2018-08-08 18:27:03 -0700 | [diff] [blame] | 209 |  | 
| Andy Hung | e2e830f | 2019-12-03 12:54:46 -0800 | [diff] [blame] | 210 |     const char *getTrackStateAsString() const { | 
 | 211 |         if (isTerminated()) { | 
 | 212 |             return "TERMINATED"; | 
 | 213 |         } | 
 | 214 |         switch (mState) { | 
 | 215 |         case IDLE: | 
 | 216 |             return "IDLE"; | 
 | 217 |         case STOPPING_1: // for Fast and Offload | 
 | 218 |             return "STOPPING_1"; | 
 | 219 |         case STOPPING_2: // for Fast and Offload | 
 | 220 |             return "STOPPING_2"; | 
 | 221 |         case STOPPED: | 
 | 222 |             return "STOPPED"; | 
 | 223 |         case RESUMING: | 
 | 224 |             return "RESUMING"; | 
 | 225 |         case ACTIVE: | 
 | 226 |             return "ACTIVE"; | 
 | 227 |         case PAUSING: | 
 | 228 |             return "PAUSING"; | 
 | 229 |         case PAUSED: | 
 | 230 |             return "PAUSED"; | 
 | 231 |         case FLUSHED: | 
 | 232 |             return "FLUSHED"; | 
 | 233 |         case STARTING_1: // for RecordTrack | 
 | 234 |             return "STARTING_1"; | 
 | 235 |         case STARTING_2: // for RecordTrack | 
 | 236 |             return "STARTING_2"; | 
 | 237 |         default: | 
 | 238 |             return "UNKNOWN"; | 
 | 239 |         } | 
 | 240 |     } | 
 | 241 |  | 
| Andy Hung | c2b11cb | 2020-04-22 09:04:01 -0700 | [diff] [blame] | 242 |     // Called by the PlaybackThread to indicate that the track is becoming active | 
 | 243 |     // and a new interval should start with a given device list. | 
 | 244 |     void logBeginInterval(const std::string& devices) { | 
 | 245 |         mTrackMetrics.logBeginInterval(devices); | 
 | 246 |     } | 
 | 247 |  | 
 | 248 |     // Called by the PlaybackThread to indicate the track is no longer active. | 
 | 249 |     void logEndInterval() { | 
 | 250 |         mTrackMetrics.logEndInterval(); | 
 | 251 |     } | 
 | 252 |  | 
 | 253 |     // Called to tally underrun frames in playback. | 
 | 254 |     virtual void tallyUnderrunFrames(size_t /* frames */) {} | 
 | 255 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 256 | protected: | 
| Mikhail Naganov | bf49308 | 2017-04-17 17:37:12 -0700 | [diff] [blame] | 257 |     DISALLOW_COPY_AND_ASSIGN(TrackBase); | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 258 |  | 
| Andy Hung | 689e82c | 2019-08-21 17:53:17 -0700 | [diff] [blame] | 259 |     void releaseCblk() { | 
 | 260 |         if (mCblk != nullptr) { | 
 | 261 |             mCblk->~audio_track_cblk_t();   // destroy our shared-structure. | 
 | 262 |             if (mClient == 0) { | 
 | 263 |                 free(mCblk); | 
 | 264 |             } | 
 | 265 |             mCblk = nullptr; | 
 | 266 |         } | 
 | 267 |     } | 
 | 268 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 269 |     // AudioBufferProvider interface | 
| Glenn Kasten | d79072e | 2016-01-06 08:41:20 -0800 | [diff] [blame] | 270 |     virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 271 |     virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); | 
 | 272 |  | 
 | 273 |     // ExtendedAudioBufferProvider interface is only needed for Track, | 
 | 274 |     // but putting it in TrackBase avoids the complexity of virtual inheritance | 
 | 275 |     virtual size_t  framesReady() const { return SIZE_MAX; } | 
 | 276 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 277 |     uint32_t channelCount() const { return mChannelCount; } | 
 | 278 |  | 
| Jean-Michel Trivi | ddf87ef | 2019-08-20 15:42:04 -0700 | [diff] [blame] | 279 |     size_t frameSize() const { return mFrameSize; } | 
 | 280 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 281 |     audio_channel_mask_t channelMask() const { return mChannelMask; } | 
 | 282 |  | 
| Glenn Kasten | 9f80dd2 | 2012-12-18 15:57:32 -0800 | [diff] [blame] | 283 |     virtual uint32_t sampleRate() const { return mSampleRate; } | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 284 |  | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 285 |     bool isStopped() const { | 
 | 286 |         return (mState == STOPPED || mState == FLUSHED); | 
 | 287 |     } | 
 | 288 |  | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 289 |     // for fast tracks and offloaded tracks only | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 290 |     bool isStopping() const { | 
 | 291 |         return mState == STOPPING_1 || mState == STOPPING_2; | 
 | 292 |     } | 
 | 293 |     bool isStopping_1() const { | 
 | 294 |         return mState == STOPPING_1; | 
 | 295 |     } | 
 | 296 |     bool isStopping_2() const { | 
 | 297 |         return mState == STOPPING_2; | 
 | 298 |     } | 
 | 299 |  | 
| Andy Hung | 2c6c3bb | 2017-06-16 14:01:45 -0700 | [diff] [blame] | 300 |     // Upper case characters are final states. | 
 | 301 |     // Lower case characters are transitory. | 
| Andy Hung | e2e830f | 2019-12-03 12:54:46 -0800 | [diff] [blame] | 302 |     const char *getTrackStateAsCodedString() const { | 
| Andy Hung | 2c6c3bb | 2017-06-16 14:01:45 -0700 | [diff] [blame] | 303 |         if (isTerminated()) { | 
 | 304 |             return "T "; | 
 | 305 |         } | 
 | 306 |         switch (mState) { | 
 | 307 |         case IDLE: | 
 | 308 |             return "I "; | 
 | 309 |         case STOPPING_1: // for Fast and Offload | 
 | 310 |             return "s1"; | 
 | 311 |         case STOPPING_2: // for Fast and Offload | 
 | 312 |             return "s2"; | 
 | 313 |         case STOPPED: | 
 | 314 |             return "S "; | 
 | 315 |         case RESUMING: | 
 | 316 |             return "r "; | 
 | 317 |         case ACTIVE: | 
 | 318 |             return "A "; | 
 | 319 |         case PAUSING: | 
 | 320 |             return "p "; | 
 | 321 |         case PAUSED: | 
 | 322 |             return "P "; | 
 | 323 |         case FLUSHED: | 
 | 324 |             return "F "; | 
 | 325 |         case STARTING_1: // for RecordTrack | 
 | 326 |             return "r1"; | 
 | 327 |         case STARTING_2: // for RecordTrack | 
 | 328 |             return "r2"; | 
 | 329 |         default: | 
 | 330 |             return "? "; | 
 | 331 |         } | 
 | 332 |     } | 
 | 333 |  | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 334 |     bool isOut() const { return mIsOut; } | 
| Glenn Kasten | d79072e | 2016-01-06 08:41:20 -0800 | [diff] [blame] | 335 |                                     // true for Track, false for RecordTrack, | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 336 |                                     // this could be a track type if needed later | 
 | 337 |  | 
 | 338 |     const wp<ThreadBase> mThread; | 
 | 339 |     /*const*/ sp<Client> mClient;   // see explanation at ~TrackBase() why not const | 
 | 340 |     sp<IMemory>         mCblkMemory; | 
 | 341 |     audio_track_cblk_t* mCblk; | 
| Glenn Kasten | d776ac6 | 2014-05-07 09:16:09 -0700 | [diff] [blame] | 342 |     sp<IMemory>         mBufferMemory;  // currently non-0 for fast RecordTrack only | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 343 |     void*               mBuffer;    // start of track buffer, typically in shared memory | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 344 |                                     // except for OutputTrack when it is in local memory | 
| Andy Hung | 8fe6803 | 2017-06-05 16:17:51 -0700 | [diff] [blame] | 345 |     size_t              mBufferSize; // size of mBuffer in bytes | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 346 |     // we don't really need a lock for these | 
 | 347 |     track_state         mState; | 
| Kevin Rocard | 1f564ac | 2018-03-29 13:53:10 -0700 | [diff] [blame] | 348 |     const audio_attributes_t mAttr; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 349 |     const uint32_t      mSampleRate;    // initial sample rate only; for tracks which | 
 | 350 |                         // support dynamic rates, the current value is in control block | 
 | 351 |     const audio_format_t mFormat; | 
 | 352 |     const audio_channel_mask_t mChannelMask; | 
| Glenn Kasten | f6ed423 | 2013-07-16 11:16:27 -0700 | [diff] [blame] | 353 |     const uint32_t      mChannelCount; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 354 |     const size_t        mFrameSize; // AudioFlinger's view of frame size in shared memory, | 
 | 355 |                                     // where for AudioTrack (but not AudioRecord), | 
 | 356 |                                     // 8-bit PCM samples are stored as 16-bit | 
 | 357 |     const size_t        mFrameCount;// size of track buffer given at createTrack() or | 
| Eric Laurent | f14db3c | 2017-12-08 14:20:36 -0800 | [diff] [blame] | 358 |                                     // createRecord(), and then adjusted as needed | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 359 |  | 
| Glenn Kasten | d848eb4 | 2016-03-08 13:42:11 -0800 | [diff] [blame] | 360 |     const audio_session_t mSessionId; | 
| Andy Hung | 1f12a8a | 2016-11-07 16:10:30 -0800 | [diff] [blame] | 361 |     uid_t               mUid; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 362 |     Vector < sp<SyncEvent> >mSyncEvents; | 
| Glenn Kasten | e3aa659 | 2012-12-04 12:22:46 -0800 | [diff] [blame] | 363 |     const bool          mIsOut; | 
| Eric Laurent | 5bba2f6 | 2016-03-18 11:14:14 -0700 | [diff] [blame] | 364 |     sp<ServerProxy>     mServerProxy; | 
| Glenn Kasten | da6ef13 | 2013-01-10 12:31:01 -0800 | [diff] [blame] | 365 |     const int           mId; | 
| Andy Hung | 8946a28 | 2018-04-19 20:04:56 -0700 | [diff] [blame] | 366 | #ifdef TEE_SINK | 
 | 367 |     NBAIO_Tee           mTee; | 
 | 368 | #endif | 
| Eric Laurent | bfb1b83 | 2013-01-07 09:53:42 -0800 | [diff] [blame] | 369 |     bool                mTerminated; | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 370 |     track_type          mType;      // must be one of TYPE_DEFAULT, TYPE_OUTPUT, TYPE_PATCH ... | 
| Eric Laurent | aaa4447 | 2014-09-12 17:41:50 -0700 | [diff] [blame] | 371 |     audio_io_handle_t   mThreadIoHandle; // I/O handle of the thread the track is attached to | 
| Eric Laurent | 20b9ef0 | 2016-12-05 11:03:16 -0800 | [diff] [blame] | 372 |     audio_port_handle_t mPortId; // unique ID for this track used by audio policy | 
| Eric Laurent | 6acd1d4 | 2017-01-04 14:23:29 -0800 | [diff] [blame] | 373 |     bool                mIsInvalid; // non-resettable latch, set by invalidate() | 
| Andy Hung | cef2daa | 2018-06-01 15:31:49 -0700 | [diff] [blame] | 374 |  | 
| Andy Hung | b68f5eb | 2019-12-03 16:49:17 -0800 | [diff] [blame] | 375 |     // It typically takes 5 threadloop mix iterations for latency to stabilize. | 
| Andy Hung | 6292112 | 2020-05-18 10:47:31 -0700 | [diff] [blame] | 376 |     // However, this can be 12+ iterations for BT. | 
 | 377 |     // To be sure, we wait for latency to dip (it usually increases at the start) | 
 | 378 |     // to assess stability and then log to MediaMetrics. | 
 | 379 |     // Rapid start / pause calls may cause inaccurate numbers. | 
 | 380 |     static inline constexpr int32_t LOG_START_COUNTDOWN = 12; | 
 | 381 |     int32_t             mLogStartCountdown = 0; // Mixer period countdown | 
 | 382 |     int64_t             mLogStartTimeNs = 0;    // Monotonic time at start() | 
 | 383 |     int64_t             mLogStartFrames = 0;    // Timestamp frames at start() | 
 | 384 |     double              mLogLatencyMs = 0.;     // Track the last log latency | 
| Andy Hung | b68f5eb | 2019-12-03 16:49:17 -0800 | [diff] [blame] | 385 |  | 
| Andy Hung | c2b11cb | 2020-04-22 09:04:01 -0700 | [diff] [blame] | 386 |     TrackMetrics        mTrackMetrics; | 
| Andy Hung | b68f5eb | 2019-12-03 16:49:17 -0800 | [diff] [blame] | 387 |  | 
| Andy Hung | cef2daa | 2018-06-01 15:31:49 -0700 | [diff] [blame] | 388 |     bool                mServerLatencySupported = false; | 
 | 389 |     std::atomic<bool>   mServerLatencyFromTrack{}; // latency from track or server timestamp. | 
 | 390 |     std::atomic<double> mServerLatencyMs{};        // last latency pushed from server thread. | 
| Andy Hung | 3028256 | 2018-08-08 18:27:03 -0700 | [diff] [blame] | 391 |     std::atomic<FrameTime> mKernelFrameTime{};     // last frame time on kernel side. | 
| Eric Laurent | 09f1ed2 | 2019-04-24 17:45:17 -0700 | [diff] [blame] | 392 |     const pid_t         mCreatorPid;  // can be different from mclient->pid() for instance | 
 | 393 |                                       // when created by NuPlayer on behalf of a client | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 394 | }; | 
 | 395 |  | 
 | 396 | // PatchProxyBufferProvider interface is implemented by PatchTrack and PatchRecord. | 
 | 397 | // it provides buffer access methods that map those of a ClientProxy (see AudioTrackShared.h) | 
 | 398 | class PatchProxyBufferProvider | 
 | 399 | { | 
 | 400 | public: | 
 | 401 |  | 
 | 402 |     virtual ~PatchProxyBufferProvider() {} | 
 | 403 |  | 
| Mikhail Naganov | caf5994 | 2019-09-25 14:05:29 -0700 | [diff] [blame] | 404 |     virtual bool        producesBufferOnDemand() const = 0; | 
| Eric Laurent | 83b8808 | 2014-06-20 18:31:16 -0700 | [diff] [blame] | 405 |     virtual status_t    obtainBuffer(Proxy::Buffer* buffer, | 
 | 406 |                                      const struct timespec *requested = NULL) = 0; | 
 | 407 |     virtual void        releaseBuffer(Proxy::Buffer* buffer) = 0; | 
| Eric Laurent | 81784c3 | 2012-11-19 14:55:58 -0800 | [diff] [blame] | 408 | }; | 
| Kevin Rocard | 45986c7 | 2018-12-18 18:22:59 -0800 | [diff] [blame] | 409 |  | 
 | 410 | class PatchTrackBase : public PatchProxyBufferProvider | 
 | 411 | { | 
 | 412 | public: | 
 | 413 |     using Timeout = std::optional<std::chrono::nanoseconds>; | 
 | 414 |                         PatchTrackBase(sp<ClientProxy> proxy, const ThreadBase& thread, | 
 | 415 |                                        const Timeout& timeout); | 
 | 416 |             void        setPeerTimeout(std::chrono::nanoseconds timeout); | 
| Andy Hung | abfab20 | 2019-03-07 19:45:54 -0800 | [diff] [blame] | 417 |             template <typename T> | 
 | 418 |             void        setPeerProxy(const sp<T> &proxy, bool holdReference) { | 
 | 419 |                             mPeerReferenceHold = holdReference ? proxy : nullptr; | 
 | 420 |                             mPeerProxy = proxy.get(); | 
 | 421 |                         } | 
 | 422 |             void        clearPeerProxy() { | 
 | 423 |                             mPeerReferenceHold.clear(); | 
 | 424 |                             mPeerProxy = nullptr; | 
 | 425 |                         } | 
| Kevin Rocard | 45986c7 | 2018-12-18 18:22:59 -0800 | [diff] [blame] | 426 |  | 
| Mikhail Naganov | caf5994 | 2019-09-25 14:05:29 -0700 | [diff] [blame] | 427 |             bool        producesBufferOnDemand() const override { return false; } | 
 | 428 |  | 
| Kevin Rocard | 45986c7 | 2018-12-18 18:22:59 -0800 | [diff] [blame] | 429 | protected: | 
 | 430 |     const sp<ClientProxy>       mProxy; | 
| Andy Hung | abfab20 | 2019-03-07 19:45:54 -0800 | [diff] [blame] | 431 |     sp<RefBase>                 mPeerReferenceHold;   // keeps mPeerProxy alive during access. | 
| Kevin Rocard | 45986c7 | 2018-12-18 18:22:59 -0800 | [diff] [blame] | 432 |     PatchProxyBufferProvider*   mPeerProxy = nullptr; | 
 | 433 |     struct timespec             mPeerTimeout{}; | 
 | 434 |  | 
 | 435 | }; |