SyncEvent: modernize C++
And add unit test mediasyncevent_tests.
Test: atest mediasyncevent_tests
Bug: 283021652
Change-Id: I37711f4271c68042f178db9370549c0c3260ace8
diff --git a/services/audioflinger/timing/Android.bp b/services/audioflinger/timing/Android.bp
index 17ce8bd..269f796 100644
--- a/services/audioflinger/timing/Android.bp
+++ b/services/audioflinger/timing/Android.bp
@@ -10,6 +10,10 @@
cc_library {
name: "libaudioflinger_timing",
+ defaults: [
+ "audioflinger_flags_defaults",
+ ],
+
host_supported: true,
srcs: [
diff --git a/services/audioflinger/timing/SyncEvent.h b/services/audioflinger/timing/SyncEvent.h
index 9912580..b5a3b40 100644
--- a/services/audioflinger/timing/SyncEvent.h
+++ b/services/audioflinger/timing/SyncEvent.h
@@ -16,43 +16,55 @@
#pragma once
-namespace android {
+#include <functional>
+#include <mutex>
+
+#include <media/AudioSystem.h>
+#include <utils/RefBase.h>
+
+namespace android::audioflinger {
class SyncEvent;
-
-typedef void (*sync_event_callback_t)(const wp<SyncEvent>& event) ;
+using SyncEventCallback = std::function<void(const wp<SyncEvent>& event)>;
class SyncEvent : public RefBase {
public:
SyncEvent(AudioSystem::sync_event_t type,
audio_session_t triggerSession,
audio_session_t listenerSession,
- sync_event_callback_t callBack,
+ const SyncEventCallback& callBack,
const wp<RefBase>& cookie)
: mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession),
- mCallback(callBack), mCookie(cookie)
+ mCookie(cookie), mCallback(callBack)
{}
- virtual ~SyncEvent() {}
-
void trigger() {
- Mutex::Autolock _l(mLock);
- if (mCallback) mCallback(wp<SyncEvent>(this));
+ std::lock_guard l(mLock);
+ if (mCallback) mCallback(wp<SyncEvent>::fromExisting(this));
}
- bool isCancelled() const { Mutex::Autolock _l(mLock); return (mCallback == NULL); }
- void cancel() { Mutex::Autolock _l(mLock); mCallback = NULL; }
+
+ bool isCancelled() const {
+ std::lock_guard l(mLock);
+ return mCallback == nullptr;
+ }
+
+ void cancel() {
+ std::lock_guard l(mLock);
+ mCallback = nullptr;
+ }
+
AudioSystem::sync_event_t type() const { return mType; }
audio_session_t triggerSession() const { return mTriggerSession; }
audio_session_t listenerSession() const { return mListenerSession; }
- wp<RefBase> cookie() const { return mCookie; }
+ const wp<RefBase>& cookie() const { return mCookie; }
private:
const AudioSystem::sync_event_t mType;
const audio_session_t mTriggerSession;
const audio_session_t mListenerSession;
- sync_event_callback_t mCallback;
const wp<RefBase> mCookie;
- mutable Mutex mLock;
+ mutable std::mutex mLock;
+ SyncEventCallback mCallback GUARDED_BY(mLock);
};
-} // namespace android
+} // namespace android::audioflinger
diff --git a/services/audioflinger/timing/tests/Android.bp b/services/audioflinger/timing/tests/Android.bp
index 29267a6..c360799 100644
--- a/services/audioflinger/timing/tests/Android.bp
+++ b/services/audioflinger/timing/tests/Android.bp
@@ -8,6 +8,31 @@
}
cc_test {
+ name: "mediasyncevent_tests",
+
+ host_supported: true,
+
+ srcs: [
+ "mediasyncevent_tests.cpp"
+ ],
+
+ header_libs: [
+ "libaudioclient_headers",
+ ],
+
+ static_libs: [
+ "liblog",
+ "libutils", // RefBase
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+}
+
+cc_test {
name: "monotonicframecounter_tests",
host_supported: true,
diff --git a/services/audioflinger/timing/tests/mediasyncevent_tests.cpp b/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
new file mode 100644
index 0000000..2922d90
--- /dev/null
+++ b/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "mediasyncevent_tests"
+
+#include "../SyncEvent.h"
+
+#include <gtest/gtest.h>
+
+using namespace android;
+using namespace android::audioflinger;
+
+namespace {
+
+TEST(MediaSyncEventTests, Basic) {
+ struct Cookie : public RefBase {};
+
+ // These variables are set by trigger().
+ bool triggered = false;
+ wp<SyncEvent> param;
+
+ constexpr auto type = AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE;
+ constexpr auto triggerSession = audio_session_t(10);
+ constexpr auto listenerSession = audio_session_t(11);
+ const SyncEventCallback callback =
+ [&](const wp<SyncEvent>& event) {
+ triggered = true;
+ param = event;
+ };
+ const auto cookie = sp<Cookie>::make();
+
+ // Since the callback uses a weak pointer to this,
+ // don't allocate on the stack.
+ auto syncEvent = sp<SyncEvent>::make(
+ type,
+ triggerSession,
+ listenerSession,
+ callback,
+ cookie);
+
+ ASSERT_EQ(type, syncEvent->type());
+ ASSERT_EQ(triggerSession, syncEvent->triggerSession());
+ ASSERT_EQ(listenerSession, syncEvent->listenerSession());
+ ASSERT_EQ(cookie, syncEvent->cookie());
+ ASSERT_FALSE(triggered);
+
+ syncEvent->trigger();
+ ASSERT_TRUE(triggered);
+ ASSERT_EQ(param, syncEvent);
+
+ ASSERT_FALSE(syncEvent->isCancelled());
+ syncEvent->cancel();
+ ASSERT_TRUE(syncEvent->isCancelled());
+}
+
+} // namespace