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 #pragma once 19 20 #include "TrackBase.h" 21 22 #include <android/os/BnExternalVibrationController.h> 23 #include <audio_utils/mutex.h> 24 #include <audio_utils/LinearMap.h> 25 #include <binder/AppOpsManager.h> 26 #include <utils/RWLock.h> 27 28 namespace android { 29 30 // Checks and monitors OP_PLAY_AUDIO 31 class OpPlayAudioMonitor : public RefBase { 32 friend class sp<OpPlayAudioMonitor>; 33 public: 34 ~OpPlayAudioMonitor() override; 35 bool hasOpPlayAudio() const; 36 37 static sp<OpPlayAudioMonitor> createIfNeeded( 38 IAfThreadBase* thread, 39 const AttributionSourceState& attributionSource, 40 const audio_attributes_t& attr, int id, 41 audio_stream_type_t streamType); 42 43 private: 44 OpPlayAudioMonitor(IAfThreadBase* thread, 45 const AttributionSourceState& attributionSource, 46 audio_usage_t usage, int id, uid_t uid); 47 void onFirstRef() override; 48 static void getPackagesForUid(uid_t uid, Vector<String16>& packages); 49 50 AppOpsManager mAppOpsManager; 51 52 class PlayAudioOpCallback : public BnAppOpsCallback { 53 public: 54 explicit PlayAudioOpCallback(const wp<OpPlayAudioMonitor>& monitor); 55 void opChanged(int32_t op, const String16& packageName) override; 56 57 private: 58 const wp<OpPlayAudioMonitor> mMonitor; 59 }; 60 61 sp<PlayAudioOpCallback> mOpCallback; 62 // called by PlayAudioOpCallback when OP_PLAY_AUDIO is updated in AppOp callback 63 void checkPlayAudioForUsage(bool doBroadcast); 64 65 wp<IAfThreadBase> mThread; 66 std::atomic_bool mHasOpPlayAudio; 67 const int32_t mUsage; // on purpose not audio_usage_t because always checked in appOps as 68 // int32_t 69 const int mId; // for logging purposes only 70 const uid_t mUid; 71 const String16 mPackageName; 72 }; 73 74 // playback track 75 class Track : public TrackBase, public virtual IAfTrack, public VolumeProvider { 76 public: 77 Track(IAfPlaybackThread* thread, 78 const sp<Client>& client, 79 audio_stream_type_t streamType, 80 const audio_attributes_t& attr, 81 uint32_t sampleRate, 82 audio_format_t format, 83 audio_channel_mask_t channelMask, 84 size_t frameCount, 85 void *buffer, 86 size_t bufferSize, 87 const sp<IMemory>& sharedBuffer, 88 audio_session_t sessionId, 89 pid_t creatorPid, 90 const AttributionSourceState& attributionSource, 91 audio_output_flags_t flags, 92 track_type type, 93 audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE, 94 /** default behaviour is to start when there are as many frames 95 * ready as possible (aka. Buffer is full). */ 96 size_t frameCountToBeReady = SIZE_MAX, 97 float speed = 1.0f, 98 bool isSpatialized = false, 99 bool isBitPerfect = false, 100 float volume = 0.0f, 101 bool muted = false); 102 ~Track() override; 103 status_t initCheck() const final; 104 void appendDumpHeader(String8& result) const final; 105 void appendDump(String8& result, bool active) const final; 106 status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, 107 audio_session_t triggerSession = AUDIO_SESSION_NONE) override; 108 void stop() override; 109 void pause() final; 110 void flush() final; 111 void destroy() final; 112 uint32_t sampleRate() const final; streamType()113 audio_stream_type_t streamType() const final { 114 return mStreamType; 115 } isOffloaded()116 bool isOffloaded() const final 117 { return (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0; } isDirect()118 bool isDirect() const final 119 { return (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0; } isOffloadedOrDirect()120 bool isOffloadedOrDirect() const final { return (mFlags 121 & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD 122 | AUDIO_OUTPUT_FLAG_DIRECT)) != 0; } isStatic()123 bool isStatic() const final { return mSharedBuffer.get() != nullptr; } 124 125 status_t setParameters(const String8& keyValuePairs) final; 126 status_t selectPresentation(int presentationId, int programId) final; 127 status_t attachAuxEffect(int EffectId) final; 128 void setAuxBuffer(int EffectId, int32_t* buffer) final; auxBuffer()129 int32_t* auxBuffer() const final { return mAuxBuffer; } setMainBuffer(float * buffer)130 void setMainBuffer(float* buffer) final { mMainBuffer = buffer; } mainBuffer()131 float* mainBuffer() const final { return mMainBuffer; } auxEffectId()132 int auxEffectId() const final { return mAuxEffectId; } 133 status_t getTimestamp(AudioTimestamp& timestamp) final; 134 void signal() final; 135 status_t getDualMonoMode(audio_dual_mono_mode_t* mode) const final; 136 status_t setDualMonoMode(audio_dual_mono_mode_t mode) final; 137 status_t getAudioDescriptionMixLevel(float* leveldB) const final; 138 status_t setAudioDescriptionMixLevel(float leveldB) final; 139 status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) const final; 140 status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) final; 141 142 // implement FastMixerState::VolumeProvider interface 143 gain_minifloat_packed_t getVolumeLR() const final; 144 145 status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) final; isFastTrack()146 bool isFastTrack() const final { return (mFlags & AUDIO_OUTPUT_FLAG_FAST) != 0; } bufferLatencyMs()147 double bufferLatencyMs() const final { 148 return isStatic() ? 0. : TrackBase::bufferLatencyMs(); 149 } 150 151 // implement volume handling. 152 media::VolumeShaper::Status applyVolumeShaper( 153 const sp<media::VolumeShaper::Configuration>& configuration, 154 const sp<media::VolumeShaper::Operation>& operation); 155 sp<media::VolumeShaper::State> getVolumeShaperState(int id) const final; getVolumeHandler()156 sp<media::VolumeHandler> getVolumeHandler() const final{ return mVolumeHandler; } 157 /** Set the computed normalized final volume of the track. 158 * !masterMute * masterVolume * streamVolume * averageLRVolume */ 159 void setFinalVolume(float volumeLeft, float volumeRight) final; getFinalVolume()160 float getFinalVolume() const final { return mFinalVolume; } getFinalVolume(float * left,float * right)161 void getFinalVolume(float* left, float* right) const final { 162 *left = mFinalVolumeLeft; 163 *right = mFinalVolumeRight; 164 } 165 166 using SourceMetadatas = std::vector<playback_track_metadata_v7_t>; 167 using MetadataInserter = std::back_insert_iterator<SourceMetadatas>; 168 /** Copy the track metadata in the provided iterator. Thread safe. */ 169 void copyMetadataTo(MetadataInserter& backInserter) const override; 170 171 172 /** Return haptic playback of the track is enabled or not, used in mixer. */ getHapticPlaybackEnabled()173 bool getHapticPlaybackEnabled() const final { return mHapticPlaybackEnabled; } 174 /** Set haptic playback of the track is enabled or not, should be 175 * set after query or get callback from vibrator service */ setHapticPlaybackEnabled(bool hapticPlaybackEnabled)176 void setHapticPlaybackEnabled(bool hapticPlaybackEnabled) final { 177 mHapticPlaybackEnabled = hapticPlaybackEnabled; 178 } 179 /** Return the haptics scale, used in mixer. */ getHapticScale()180 os::HapticScale getHapticScale() const final { return mHapticScale; } 181 /** Return the maximum amplitude allowed for haptics data, used in mixer. */ getHapticMaxAmplitude()182 float getHapticMaxAmplitude() const final { return mHapticMaxAmplitude; } 183 /** Set intensity of haptic playback, should be set after querying vibrator service. */ setHapticScale(os::HapticScale hapticScale)184 void setHapticScale(os::HapticScale hapticScale) final { 185 if (os::isValidHapticScale(hapticScale)) { 186 mHapticScale = hapticScale; 187 setHapticPlaybackEnabled(!mHapticScale.isScaleMute()); 188 } 189 } 190 /** Set maximum amplitude allowed for haptic data, should be set after querying 191 * vibrator service. 192 */ setHapticMaxAmplitude(float maxAmplitude)193 void setHapticMaxAmplitude(float maxAmplitude) final { 194 mHapticMaxAmplitude = maxAmplitude; 195 } getExternalVibration()196 sp<os::ExternalVibration> getExternalVibration() const final { return mExternalVibration; } 197 198 // This function should be called with holding thread lock. 199 void updateTeePatches_l() final REQUIRES(audio_utils::ThreadBase_Mutex) 200 EXCLUDES_BELOW_ThreadBase_Mutex; 201 void setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) final; 202 tallyUnderrunFrames(size_t frames)203 void tallyUnderrunFrames(size_t frames) final { 204 if (isOut()) { // we expect this from output tracks only 205 mAudioTrackServerProxy->tallyUnderrunFrames(frames); 206 // Fetch absolute numbers from AudioTrackShared as it counts 207 // contiguous underruns as a one -- we want a consistent number. 208 // TODO: isolate this counting into a class. 209 mTrackMetrics.logUnderruns(mAudioTrackServerProxy->getUnderrunCount(), 210 mAudioTrackServerProxy->getUnderrunFrames()); 211 } 212 } 213 getOutputFlags()214 audio_output_flags_t getOutputFlags() const final { return mFlags; } getSpeed()215 float getSpeed() const final { return mSpeed; } isSpatialized()216 bool isSpatialized() const final { return mIsSpatialized; } isBitPerfect()217 bool isBitPerfect() const final { return mIsBitPerfect; } 218 219 /** 220 * Updates the mute state and notifies the audio service. Call this only when holding player 221 * thread lock. 222 */ 223 void processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState) final; 224 getInternalMute()225 bool getInternalMute() const final { return mInternalMute; } setInternalMute(bool muted)226 void setInternalMute(bool muted) final { mInternalMute = muted; } 227 228 // VolumePortInterface implementation 229 void setPortVolume(float volume) override; 230 void setPortMute(bool muted) override; getPortVolume()231 float getPortVolume() const override { return mVolume; } getPortMute()232 bool getPortMute() const override { return mMutedFromPort; } 233 trackFlagsAsString()234 std::string trackFlagsAsString() const final { return toString(mFlags); } 235 236 protected: 237 238 DISALLOW_COPY_AND_ASSIGN(Track); 239 240 // AudioBufferProvider interface 241 status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override; 242 void releaseBuffer(AudioBufferProvider::Buffer* buffer) override; 243 244 // ExtendedAudioBufferProvider interface 245 size_t framesReady() const override; 246 int64_t framesReleased() const override; 247 void onTimestamp(const ExtendedTimestamp ×tamp) override; 248 249 // Used by thread isPausing()250 bool isPausing() const final { return mState == PAUSING; } isPaused()251 bool isPaused() const final { return mState == PAUSED; } isResuming()252 bool isResuming() const final { return mState == RESUMING; } 253 bool isReady() const final; setPaused()254 void setPaused() final { mState = PAUSED; } 255 void reset() final; isFlushPending()256 bool isFlushPending() const final { return mFlushHwPending; } 257 void flushAck() final; 258 bool isResumePending() const final; 259 void resumeAck() final; 260 // For direct or offloaded tracks ensure that the pause state is acknowledged 261 // by the playback thread in case of an immediate flush. isPausePending()262 bool isPausePending() const final { return mPauseHwPending; } 263 void pauseAck() final; 264 void updateTrackFrameInfo(int64_t trackFramesReleased, int64_t sinkFramesWritten, 265 uint32_t halSampleRate, const ExtendedTimestamp& timeStamp) final; 266 sharedBuffer()267 sp<IMemory> sharedBuffer() const final { return mSharedBuffer; } 268 269 // presentationComplete checked by frames. (Mixed Tracks). 270 // framesWritten is cumulative, never reset, and is shared all tracks 271 // audioHalFrames is derived from output latency 272 bool presentationComplete(int64_t framesWritten, size_t audioHalFrames) final; 273 274 // presentationComplete checked by time. (Direct Tracks). 275 bool presentationComplete(uint32_t latencyMs) final; 276 resetPresentationComplete()277 void resetPresentationComplete() final { 278 mPresentationCompleteFrames = 0; 279 mPresentationCompleteTimeNs = 0; 280 } 281 282 // notifyPresentationComplete is called when presentationComplete() detects 283 // that the track is finished stopping. 284 void notifyPresentationComplete(); 285 286 void signalClientFlag(int32_t flag); 287 288 void triggerEvents(AudioSystem::sync_event_t type) final; 289 void invalidate() final; 290 void disable() final; 291 bool isDisabled() const final; 292 fastIndex()293 int& fastIndex() final { return mFastIndex; } isPlaybackRestricted()294 bool isPlaybackRestricted() const final { 295 // The monitor is only created for tracks that can be silenced. 296 return mOpPlayAudioMonitor ? !mOpPlayAudioMonitor->hasOpPlayAudio() : false; } 297 audioTrackServerProxy()298 const sp<AudioTrackServerProxy>& audioTrackServerProxy() const final { 299 return mAudioTrackServerProxy; 300 } hasVolumeController()301 bool hasVolumeController() const final { return mHasVolumeController; } setHasVolumeController(bool hasVolumeController)302 void setHasVolumeController(bool hasVolumeController) final { 303 mHasVolumeController = hasVolumeController; 304 } setCachedVolume(float volume)305 void setCachedVolume(float volume) final { 306 mCachedVolume = volume; 307 } setResetDone(bool resetDone)308 void setResetDone(bool resetDone) final { 309 mResetDone = resetDone; 310 } asExtendedAudioBufferProvider()311 ExtendedAudioBufferProvider* asExtendedAudioBufferProvider() final { 312 return this; 313 } asVolumeProvider()314 VolumeProvider* asVolumeProvider() final { 315 return this; 316 } 317 fillingStatus()318 FillingStatus& fillingStatus() final { return mFillingStatus; } retryCount()319 int8_t& retryCount() final { return mRetryCount; } fastTrackUnderruns()320 FastTrackUnderruns& fastTrackUnderruns() final { return mObservedUnderruns; } 321 322 protected: 323 mutable FillingStatus mFillingStatus; 324 int8_t mRetryCount; 325 326 // see comment at ~Track for why this can't be const 327 sp<IMemory> mSharedBuffer; 328 329 bool mResetDone; 330 const audio_stream_type_t mStreamType; 331 float *mMainBuffer; 332 333 int32_t *mAuxBuffer; 334 int mAuxEffectId; 335 bool mHasVolumeController; 336 337 // access these three variables only when holding thread lock. 338 LinearMap<int64_t> mFrameMap; // track frame to server frame mapping 339 340 ExtendedTimestamp mSinkTimestamp; 341 342 sp<media::VolumeHandler> mVolumeHandler; // handles multiple VolumeShaper configs and operations 343 344 sp<OpPlayAudioMonitor> mOpPlayAudioMonitor; 345 346 bool mHapticPlaybackEnabled = false; // indicates haptic playback enabled or not 347 // scale to play haptic data 348 os::HapticScale mHapticScale = os::HapticScale::mute(); 349 // max amplitude allowed for haptic data 350 float mHapticMaxAmplitude = NAN; 351 class AudioVibrationController : public os::BnExternalVibrationController { 352 public: AudioVibrationController(Track * track)353 explicit AudioVibrationController(Track* track) : mTrack(track) {} 354 binder::Status mute(/*out*/ bool *ret) override; 355 binder::Status unmute(/*out*/ bool *ret) override; 356 private: 357 Track* const mTrack; 358 bool setMute(bool muted); 359 }; 360 sp<AudioVibrationController> mAudioVibrationController; 361 sp<os::ExternalVibration> mExternalVibration; 362 363 audio_dual_mono_mode_t mDualMonoMode = AUDIO_DUAL_MONO_MODE_OFF; 364 float mAudioDescriptionMixLevel = -std::numeric_limits<float>::infinity(); 365 audio_playback_rate_t mPlaybackRateParameters = AUDIO_PLAYBACK_RATE_INITIALIZER; 366 367 private: 368 void interceptBuffer(const AudioBufferProvider::Buffer& buffer); 369 // Must hold thread lock to access tee patches 370 template <class F> forEachTeePatchTrack_l(F f)371 void forEachTeePatchTrack_l(F f) { 372 RWLock::AutoRLock readLock(mTeePatchesRWLock); 373 for (auto& tp : mTeePatches) { f(tp.patchTrack); } 374 }; 375 376 void populateUsageAndContentTypeFromStreamType(); 377 378 size_t mPresentationCompleteFrames = 0; // (Used for Mixed tracks) 379 // The number of frames written to the 380 // audio HAL when this track is considered fully rendered. 381 // Zero means not monitoring. 382 int64_t mPresentationCompleteTimeNs = 0; // (Used for Direct tracks) 383 // The time when this track is considered fully rendered. 384 // Zero means not monitoring. 385 386 // The following fields are only for fast tracks, and should be in a subclass 387 int mFastIndex; // index within FastMixerState::mFastTracks[]; 388 // either mFastIndex == -1 if not isFastTrack() 389 // or 0 < mFastIndex < FastMixerState::kMaxFast because 390 // index 0 is reserved for normal mixer's submix; 391 // index is allocated statically at track creation time 392 // but the slot is only used if track is active 393 FastTrackUnderruns mObservedUnderruns; // Most recently observed value of 394 // mFastMixerDumpState.mTracks[mFastIndex].mUnderruns 395 volatile float mCachedVolume; // combined master volume and stream type volume; 396 // 'volatile' means accessed without lock or 397 // barrier, but is read/written atomically 398 float mFinalVolume; // combine master volume, stream type volume and track volume 399 float mFinalVolumeLeft; // combine master volume, stream type volume and track 400 // volume 401 float mFinalVolumeRight; // combine master volume, stream type volume and track 402 // volume 403 sp<AudioTrackServerProxy> mAudioTrackServerProxy; 404 bool mResumeToStopping; // track was paused in stopping state. 405 bool mFlushHwPending; // track requests for thread flush 406 bool mPauseHwPending = false; // direct/offload track request for thread pause 407 audio_output_flags_t mFlags; 408 TeePatches mTeePatches; 409 std::optional<TeePatches> mTeePatchesToUpdate; 410 RWLock mTeePatchesRWLock; 411 const float mSpeed; 412 const bool mIsSpatialized; 413 const bool mIsBitPerfect; 414 415 // TODO: replace PersistableBundle with own struct 416 // access these two variables only when holding player thread lock. 417 std::unique_ptr<os::PersistableBundle> mMuteEventExtras; 418 std::atomic<mute_state_t> mMuteState; 419 std::atomic<bool> mMutedFromPort; 420 bool mInternalMute = false; 421 std::atomic<float> mVolume = 0.0f; 422 }; // end of Track 423 424 425 // playback track, used by DuplicatingThread 426 class OutputTrack : public Track, public IAfOutputTrack { 427 public: 428 429 class Buffer : public AudioBufferProvider::Buffer { 430 public: 431 void *mBuffer; 432 }; 433 434 OutputTrack(IAfPlaybackThread* thread, 435 IAfDuplicatingThread* sourceThread, 436 uint32_t sampleRate, 437 audio_format_t format, 438 audio_channel_mask_t channelMask, 439 size_t frameCount, 440 const AttributionSourceState& attributionSource); 441 ~OutputTrack() override; 442 443 status_t start(AudioSystem::sync_event_t event = 444 AudioSystem::SYNC_EVENT_NONE, 445 audio_session_t triggerSession = AUDIO_SESSION_NONE) final; 446 void stop() final; 447 ssize_t write(void* data, uint32_t frames) final; bufferQueueEmpty()448 bool bufferQueueEmpty() const final { return mBufferQueue.size() == 0; } isActive()449 bool isActive() const final { return mActive; } 450 451 void copyMetadataTo(MetadataInserter& backInserter) const final; 452 /** Set the metadatas of the upstream tracks. Thread safe. */ 453 void setMetadatas(const SourceMetadatas& metadatas) final; 454 /** returns client timestamp to the upstream duplicating thread. */ getClientProxyTimestamp()455 ExtendedTimestamp getClientProxyTimestamp() const final { 456 // server - kernel difference is not true latency when drained 457 // i.e. mServerProxy->isDrained(). 458 ExtendedTimestamp timestamp; 459 (void) mClientProxy->getTimestamp(×tamp); 460 // On success, the timestamp LOCATION_SERVER and LOCATION_KERNEL 461 // entries will be properly filled. If getTimestamp() 462 // is unsuccessful, then a default initialized timestamp 463 // (with mTimeNs[] filled with -1's) is returned. 464 return timestamp; 465 } 466 private: 467 status_t obtainBuffer(AudioBufferProvider::Buffer* buffer, 468 uint32_t waitTimeMs); 469 void queueBuffer(Buffer& inBuffer); 470 void clearBufferQueue(); 471 472 void restartIfDisabled() override; 473 474 // Maximum number of pending buffers allocated by OutputTrack::write() 475 static const uint8_t kMaxOverFlowBuffers = 10; 476 477 Vector < Buffer* > mBufferQueue; 478 AudioBufferProvider::Buffer mOutBuffer; 479 bool mActive; 480 IAfDuplicatingThread* const mSourceThread; // for waitTimeMs() in write() 481 sp<AudioTrackClientProxy> mClientProxy; 482 483 /** Attributes of the source tracks. 484 * 485 * This member must be accessed with mTrackMetadatasMutex taken. 486 * There is one writer (duplicating thread) and one reader (downstream mixer). 487 * 488 * That means that the duplicating thread can block the downstream mixer 489 * thread and vice versa for the time of the copy. 490 * If this becomes an issue, the metadata could be stored in an atomic raw pointer, 491 * and a exchange with nullptr and delete can be used. 492 * Alternatively a read-copy-update might be implemented. 493 */ 494 SourceMetadatas mTrackMetadatas; 495 /** Protects mTrackMetadatas against concurrent access. */ trackMetadataMutex()496 audio_utils::mutex& trackMetadataMutex() const { return mTrackMetadataMutex; } 497 mutable audio_utils::mutex mTrackMetadataMutex{ 498 audio_utils::MutexOrder::kOutputTrack_TrackMetadataMutex}; 499 }; // end of OutputTrack 500 501 // playback track, used by PatchPanel 502 class PatchTrack : public Track, public PatchTrackBase, public IAfPatchTrack { 503 public: 504 PatchTrack(IAfPlaybackThread* playbackThread, 505 audio_stream_type_t streamType, 506 uint32_t sampleRate, 507 audio_channel_mask_t channelMask, 508 audio_format_t format, 509 size_t frameCount, 510 void *buffer, 511 size_t bufferSize, 512 audio_output_flags_t flags, 513 const Timeout& timeout = {}, 514 size_t frameCountToBeReady = 1, /** Default behaviour is to start 515 * as soon as possible to have 516 * the lowest possible latency 517 * even if it might glitch. */ 518 float speed = 1.0f, 519 float volume = 1.0f, 520 bool muted = false); 521 ~PatchTrack() override; 522 523 size_t framesReady() const final; 524 525 status_t start(AudioSystem::sync_event_t event = 526 AudioSystem::SYNC_EVENT_NONE, 527 audio_session_t triggerSession = AUDIO_SESSION_NONE) final; 528 529 // AudioBufferProvider interface 530 status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) final; 531 void releaseBuffer(AudioBufferProvider::Buffer* buffer) final; 532 533 // PatchProxyBufferProvider interface 534 status_t obtainBuffer(Proxy::Buffer* buffer, const struct timespec* timeOut = nullptr) final; 535 void releaseBuffer(Proxy::Buffer* buffer) final; 536 537 private: 538 void restartIfDisabled() override; 539 }; // end of PatchTrack 540 541 } // namespace android 542