PatchPanel: follow up to remove false warning from ~Patch
When a new patch is being added to mPatches in this line:
mPatches.insert(std::make_pair(*handle, std::move(newPatch)));
the source of the move--`newPatch` remains intact, and if it
is a software patch, it has playback and record patch handles
remaining to be non-NONE values. Thus, on destruction it falsely
warns that it hasn't been cleared.
The solution is to define a move constructor for Endpoint which
"transfers" patch handle ownership.
Also delete copy constructors to make sure that each Patch is
a unique resource.
Test: create a software patch, watch logcat
Change-Id: I41ea2dff087696252132e79d827e705378baaf8f
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 5a68960..f4e43e2 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -46,6 +46,16 @@
template<typename ThreadType, typename TrackType>
class Endpoint {
public:
+ Endpoint() = default;
+ Endpoint(Endpoint&& other) { *this = std::move(other); }
+ Endpoint& operator=(Endpoint&& other) {
+ ALOGE_IF(mHandle != AUDIO_PATCH_HANDLE_NONE,
+ "A non empty Patch Endpoint leaked, handle %d", mHandle);
+ *this = other;
+ other.mHandle = AUDIO_PATCH_HANDLE_NONE;
+ return *this;
+ }
+
status_t checkTrack(TrackType *trackOrNull) const {
if (trackOrNull == nullptr) return NO_MEMORY;
return trackOrNull->initCheck();
@@ -82,6 +92,9 @@
void stopTrack() { if (mTrack) mTrack->stop(); }
private:
+ Endpoint(const Endpoint&) = default;
+ Endpoint& operator=(const Endpoint&) = default;
+
sp<ThreadType> mThread;
bool mCloseThread = true;
audio_patch_handle_t mHandle = AUDIO_PATCH_HANDLE_NONE;
@@ -92,6 +105,10 @@
public:
explicit Patch(const struct audio_patch &patch) : mAudioPatch(patch) {}
~Patch();
+ Patch(const Patch&) = delete;
+ Patch(Patch&&) = default;
+ Patch& operator=(const Patch&) = delete;
+ Patch& operator=(Patch&&) = default;
status_t createConnections(PatchPanel *panel);
void clearConnections(PatchPanel *panel);