diff options
author | 2024-10-25 17:04:33 -0700 | |
---|---|---|
committer | 2024-10-29 17:45:09 +0000 | |
commit | 8f33f462daaee6c906a6fcf26f28c4fca32425d1 (patch) | |
tree | 2bdf46eaa09692608c9febdb87e0d206bf5081af | |
parent | a8eeda6cd6cf1f19a23f6cff813ea169c995559e (diff) |
Remove libbluetooth-gdx
ModuleMainloop, ModuleJniloop are thin wrappers on top
of do_in_main_thread, do_in_jni_thread, and are only used
in tests.
Remove the associated tests libbluetooth-gdx-test for
dumpsys and lifecylce due to lack of comment and
documentation (only run in postsubmit).
Bug: 331817295
Test: m com.android.btservices
Flag: EXEMPT, dead code removal
Change-Id: I84d810e3f5a371013e1cc3a17561ccaa66f65164
26 files changed, 3 insertions, 3088 deletions
diff --git a/TEST_MAPPING b/TEST_MAPPING index 5da35c4dc0..bd98b7d91c 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -308,9 +308,6 @@ "name": "bluetooth-test-audio-hal-a2dp-provider-info" }, { - "name": "bluetooth_test_gdx_unit" - }, - { "name": "net_test_bta_jv" }, { diff --git a/android/app/Android.bp b/android/app/Android.bp index f038a3f43b..2bac3ba017 100644 --- a/android/app/Android.bp +++ b/android/app/Android.bp @@ -106,7 +106,6 @@ cc_library_shared { "libbase", "libbluetooth", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_core_rs", "libbluetooth_core_rs_bridge", diff --git a/system/audio_hal_interface/Android.bp b/system/audio_hal_interface/Android.bp index 1e5652c747..987b859214 100644 --- a/system/audio_hal_interface/Android.bp +++ b/system/audio_hal_interface/Android.bp @@ -228,7 +228,6 @@ cc_defaults { "libFraunhoferAAC", "libbase", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-protos", "libbluetooth-types", "libbluetooth_core_rs", diff --git a/system/audio_hal_interface/fuzzer/Android.bp b/system/audio_hal_interface/fuzzer/Android.bp index e55a9d62ad..93a734b02f 100644 --- a/system/audio_hal_interface/fuzzer/Android.bp +++ b/system/audio_hal_interface/fuzzer/Android.bp @@ -60,7 +60,6 @@ cc_defaults { "libFraunhoferAAC", "libbase", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-protos", "libbluetooth-types", "libbluetooth_core_rs", diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 2d3d40e3fd..2402f95c07 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -298,7 +298,6 @@ cc_test { "libbase", "libbluetooth-dumpsys", "libbluetooth-for-tests", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_core_rs", "libbluetooth_crypto_toolbox", diff --git a/system/btif/BUILD.gn b/system/btif/BUILD.gn index 5129a1efb3..884dc60ba3 100644 --- a/system/btif/BUILD.gn +++ b/system/btif/BUILD.gn @@ -114,7 +114,6 @@ static_library("btif") { "//bt/system:libbt-platform-protos-lite", "//bt/system/common", "//bt/system/profile/avrcp:profile_avrcp", - "//bt/system/gd:libbluetooth-gdx", ] configs += [ diff --git a/system/gd/Android.bp b/system/gd/Android.bp index 579aae7d44..c74cff9adb 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -129,6 +129,7 @@ cc_defaults { ":BluetoothNeighborSources", ":BluetoothOsSources", ":BluetoothPacketSources", + ":BluetoothShimSources", ":BluetoothStorageSources", "module.cc", "module_dumper.cc", @@ -173,7 +174,7 @@ cc_defaults { ], } -cc_library { +cc_library_static { name: "libbluetooth_gd", defaults: [ "libbluetooth_gd_defaults", @@ -192,27 +193,6 @@ cc_library { } cc_library_static { - name: "libbluetooth-gdx", - defaults: [ - "libbluetooth_gd_defaults", - ], - srcs: [ - ":BluetoothShimSources", - ], - include_dirs: [ - "packages/modules/Bluetooth/system", - ], - apex_available: [ - "com.android.btservices", - ], - min_sdk_version: "31", - static_libs: [ - "bluetooth_flags_c_lib", - "libchrome", - ], -} - -cc_library { name: "libbluetooth_gd_fuzzing", defaults: [ "libbluetooth_gd_defaults", @@ -236,7 +216,7 @@ cc_library { ], } -cc_library { +cc_library_static { name: "libbluetooth_gd_unit_tests", defaults: [ "libbluetooth_gd_defaults", @@ -297,7 +277,6 @@ cc_binary { "breakpad_client", "libPlatformProperties", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-protos", "libbluetooth-types", "libbluetooth_crypto_toolbox", @@ -498,63 +477,6 @@ cc_test { } cc_test { - name: "bluetooth_test_gdx_unit", - test_suites: ["device-tests"], - defaults: [ - "aconfig_lib_cc_shared_link.defaults", - "gd_defaults", - "mts_defaults", - ], - include_dirs: [ - "packages/modules/Bluetooth/system", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/stack/include", - "packages/modules/Bluetooth/system/types", - ], - host_supported: true, - srcs: [ - ":BluetoothDumpsysTestSources", - ":BluetoothShimTestSources", - ":TestCommonMockFunctions", - ":TestMockMainShimStack", - "module_gdx_unittest.cc", - "module_jniloop_unittest.cc", - "module_mainloop_unittest.cc", - "module_state_dumper_unittest.cc", - ], - generated_headers: [ - "BluetoothGeneratedBundlerSchema_h_bfbs", - "BluetoothGeneratedDumpsysDataSchema_h", - "BluetoothGeneratedDumpsysInternalTestData_h", - "BluetoothGeneratedDumpsysTestData_h", - ], - static_libs: [ - "bluetooth_flags_c_lib_for_test", - "libbase", - "libbluetooth-dumpsys", - "libbluetooth-dumpsys-test", - "libbluetooth-dumpsys-unittest", - "libbluetooth-gdx", - "libbluetooth_gd", - "libbluetooth_log", - "libbt-btu-main-thread", - "libbt-common", - "libbt-jni-thread", - "libchrome", - "libevent", - "libflatbuffers-cpp", - "libgmock", - "liblog", - "libosi", - "server_configurable_flags", - ], - sanitize: { - address: true, - }, - min_sdk_version: "Tiramisu", -} - -cc_test { name: "bluetooth_packet_parser_test", test_suites: ["general-tests"], defaults: [ diff --git a/system/gd/BUILD.gn b/system/gd/BUILD.gn index 5786a5b700..fa8a64fd25 100644 --- a/system/gd/BUILD.gn +++ b/system/gd/BUILD.gn @@ -53,17 +53,6 @@ group("gd_default_deps") { ] } -static_library("libbluetooth-gdx") { - include_dirs = [ - "packages/modules/Bluetooth/system", - ] - configs += [ ":gd_defaults" ] - deps = [ - "//bt/system/gd:gd_default_deps", - "//bt/system/gd/shim:BluetoothShimSources", - ] -} - static_library("libbluetooth_gd") { sources = [ "module.cc", diff --git a/system/gd/module_gdx_unittest.cc b/system/gd/module_gdx_unittest.cc deleted file mode 100644 index 9d9ee4c7c8..0000000000 --- a/system/gd/module_gdx_unittest.cc +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Copyright 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. - */ - -#include "module_gdx_unittest.h" - -#include <base/callback.h> -#include <base/functional/bind.h> -#include <base/location.h> -#include <base/threading/platform_thread.h> -#include <sys/syscall.h> - -#include <chrono> -#include <future> -#include <string> - -#include "common/bind.h" -#include "common/contextual_callback.h" -#include "gtest/gtest.h" -#include "module.h" -#include "os/handler.h" - -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -using namespace bluetooth; - -namespace { -constexpr int sync_timeout_in_ms = 3000; - -std::promise<pid_t> gdx_external_function_promise; -std::promise<pid_t> private_impl_promise; -std::promise<pid_t> protected_method_promise; - -} // namespace - -// Global function with C linkage -void external_function_gdx(int /* a */, double /* b */, char /* c */) { - gdx_external_function_promise.set_value(base::PlatformThread::CurrentId()); -} - -// Module private implementation that is inaccessible externally -struct TestGdxModule::PrivateImpl : public ModuleMainloop, public ModuleJniloop { - const int kMaxTestGdxModuleRecurseDepth = 10; - - void privateCallableMethod(int /* a */, double /* b */, char /* c */) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - } - - void repostMethodTest(int /* a */, double /* b */, char /* c */) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - } - - void privateCallableRepostOnMainMethod(std::shared_ptr<TestGdxModule::PrivateImpl> ptr, int a, - double b, char c) { - PostMethodOnMain(ptr, &PrivateImpl::repostMethodTest, a, b, c); - } - - void privateCallableRepostOnJniMethod(std::shared_ptr<TestGdxModule::PrivateImpl> ptr, int a, - double b, char c) { - PostMethodOnJni(ptr, &PrivateImpl::repostMethodTest, a, b, c); - } - - void privateCallableRecursiveOnMainMethod(std::shared_ptr<TestGdxModule::PrivateImpl> ptr, - int depth, double b, char c) { - if (depth > kMaxTestGdxModuleRecurseDepth) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - return; - } - PostMethodOnMain(ptr, &PrivateImpl::privateCallableRecursiveOnMainMethod, ptr, depth + 1, b, c); - } - - void privateCallableRecursiveOnJniMethod(std::shared_ptr<TestGdxModule::PrivateImpl> ptr, - int depth, double b, char c) { - if (depth > kMaxTestGdxModuleRecurseDepth) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - return; - } - PostMethodOnJni(ptr, &PrivateImpl::privateCallableRecursiveOnJniMethod, ptr, depth + 1, b, c); - } -}; - -// Protected module method executed on handler -void TestGdxModule::call_on_handler_protected_method(int loop_tid, int a, int b, int c) { - protected_method_promise = std::promise<pid_t>(); - auto future = protected_method_promise.get_future(); - CallOn(this, &TestGdxModule::protected_method, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Global external function executed on main loop -void TestGdxModule::call_on_main_external_function(int loop_tid, int a, double b, char c) { - gdx_external_function_promise = std::promise<pid_t>(); - auto future = gdx_external_function_promise.get_future(); - PostFunctionOnMain(&external_function_gdx, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop -void TestGdxModule::call_on_main(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise<pid_t>(); - auto future = private_impl_promise.get_future(); - PostMethodOnMain(pimpl_, &TestGdxModule::PrivateImpl::privateCallableMethod, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop and reposted -void TestGdxModule::call_on_main_repost(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise<pid_t>(); - auto future = private_impl_promise.get_future(); - PostMethodOnMain(pimpl_, &TestGdxModule::PrivateImpl::privateCallableRepostOnMainMethod, pimpl_, - a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop recursively -void TestGdxModule::call_on_main_recurse(int loop_tid, int depth, int b, int c) { - private_impl_promise = std::promise<pid_t>(); - auto future = private_impl_promise.get_future(); - PostMethodOnMain(pimpl_, &TestGdxModule::PrivateImpl::privateCallableRecursiveOnMainMethod, - pimpl_, depth, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Global external function executed on main loop -void TestGdxModule::call_on_jni_external_function(int loop_tid, int a, double b, char c) { - gdx_external_function_promise = std::promise<pid_t>(); - auto future = gdx_external_function_promise.get_future(); - PostFunctionOnJni(&external_function_gdx, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop -void TestGdxModule::call_on_jni(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise<pid_t>(); - auto future = private_impl_promise.get_future(); - PostMethodOnJni(pimpl_, &TestGdxModule::PrivateImpl::privateCallableMethod, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop and reposted -void TestGdxModule::call_on_jni_repost(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise<pid_t>(); - auto future = private_impl_promise.get_future(); - PostMethodOnJni(pimpl_, &TestGdxModule::PrivateImpl::privateCallableRepostOnJniMethod, pimpl_, a, - b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop recursively -void TestGdxModule::call_on_jni_recurse(int loop_tid, int depth, int b, int c) { - private_impl_promise = std::promise<pid_t>(); - auto future = private_impl_promise.get_future(); - PostMethodOnJni(pimpl_, &TestGdxModule::PrivateImpl::privateCallableRecursiveOnJniMethod, pimpl_, - depth, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} -void TestGdxModule::protected_method(int /* a */, int /* b */, int /* c */) { - protected_method_promise.set_value(base::PlatformThread::CurrentId()); -} - -bool TestGdxModule::IsStarted() const { return pimpl_ != nullptr; } - -void TestGdxModule::Start() { - ASSERT_FALSE(IsStarted()); - pimpl_ = std::make_shared<TestGdxModule::PrivateImpl>(); -} - -void TestGdxModule::Stop() { - ASSERT_TRUE(IsStarted()); - pimpl_.reset(); -} - -std::string TestGdxModule::ToString() const { return "TestGdxModule"; } - -const bluetooth::ModuleFactory TestGdxModule::Factory = - bluetooth::ModuleFactory([]() { return new TestGdxModule(); }); - -void TestGdxModule::set_callback(common::ContextualCallback<void(std::string)> callback) { - call_many_ = callback; -} - -void TestGdxModule::set_once_callback(common::ContextualOnceCallback<void(std::string)> callback) { - call_once_ = std::move(callback); -} - -void TestGdxModule::call_callback_on_handler(std::string message) { - GetHandler()->Post(common::BindOnce([](common::ContextualCallback<void(std::string)> callback, - std::string message) { callback(message); }, - call_many_, message)); -} - -void TestGdxModule::call_once_callback_on_handler(std::string message) { - GetHandler()->Post(common::BindOnce([](common::ContextualOnceCallback<void(std::string)> callback, - std::string message) { callback(message); }, - std::move(call_once_), message)); -} - -void TestGdxModule::call_callback_on_main(std::string message) { - post_on_bt_main([message, this]() { call_many_(message); }); -} - -void TestGdxModule::call_once_callback_on_main(std::string message) { - post_on_bt_main([message, this]() { call_once_(message); }); -} - -void TestGdxModule::call_callback_on_jni(std::string message) { - post_on_bt_jni([message, this]() { call_many_(message); }); -} - -void TestGdxModule::call_once_callback_on_jni(std::string message) { - post_on_bt_jni([message, this]() { call_once_(message); }); -} - -// -// Module GDx Testing Below -// -class ModuleGdxTest : public ::testing::Test { -protected: - void SetUp() override { - test_framework_tid_ = base::PlatformThread::CurrentId(); - module_ = new TestGdxModule(); - main_thread_start_up(); - mainloop_tid_ = get_mainloop_tid(); - jni_thread_startup(); - jniloop_tid_ = get_jniloop_tid(); - } - - void TearDown() override { - sync_main_handler(); - main_thread_shut_down(); - jni_thread_shutdown(); - delete module_; - } - - void sync_main_handler() { - std::promise promise = std::promise<void>(); - std::future future = promise.get_future(); - post_on_bt_main([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(sync_timeout_in_ms)); - } - - void sync_jni_handler() { - std::promise promise = std::promise<void>(); - std::future future = promise.get_future(); - post_on_bt_jni([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(sync_timeout_in_ms)); - } - - static pid_t get_mainloop_tid() { - std::promise<pid_t> pid_promise = std::promise<pid_t>(); - auto future = pid_promise.get_future(); - post_on_bt_main([&pid_promise]() { pid_promise.set_value(base::PlatformThread::CurrentId()); }); - return future.get(); - } - - static pid_t get_jniloop_tid() { - std::promise<pid_t> pid_promise = std::promise<pid_t>(); - auto future = pid_promise.get_future(); - post_on_bt_jni([&pid_promise]() { pid_promise.set_value(base::PlatformThread::CurrentId()); }); - return future.get(); - } - - pid_t test_framework_tid_{-1}; - pid_t mainloop_tid_{-1}; - pid_t jniloop_tid_{-1}; - TestModuleRegistry module_registry_; - TestGdxModule* module_; -}; - -class ModuleGdxWithStackTest : public ModuleGdxTest { -protected: - void SetUp() override { - ModuleGdxTest::SetUp(); - module_registry_.InjectTestModule(&TestGdxModule::Factory, module_ /* pass ownership */); - module_ = nullptr; // ownership is passed - handler_tid_ = get_handler_tid(module_registry_.GetTestModuleHandler(&TestGdxModule::Factory)); - } - - static pid_t get_handler_tid(os::Handler* handler) { - std::promise<pid_t> handler_tid_promise = std::promise<pid_t>(); - std::future<pid_t> future = handler_tid_promise.get_future(); - handler->Post(common::BindOnce( - [](std::promise<pid_t> promise) { - promise.set_value(base::PlatformThread::CurrentId()); - }, - std::move(handler_tid_promise))); - return future.get(); - } - - void TearDown() override { - module_registry_.StopAll(); - ModuleGdxTest::TearDown(); - } - - TestGdxModule* Mod() { return module_registry_.GetModuleUnderTest<TestGdxModule>(); } - - pid_t handler_tid_{-1}; -}; - -TEST_F(ModuleGdxTest, nop) {} - -TEST_F(ModuleGdxTest, lifecycle) { - ::bluetooth::os::Thread* thread = - new bluetooth::os::Thread("Name", bluetooth::os::Thread::Priority::REAL_TIME); - ASSERT_FALSE(module_registry_.IsStarted<TestGdxModule>()); - module_registry_.Start<TestGdxModule>(thread); - ASSERT_TRUE(module_registry_.IsStarted<TestGdxModule>()); - module_registry_.StopAll(); - ASSERT_FALSE(module_registry_.IsStarted<TestGdxModule>()); - delete thread; -} - -// internal handler -TEST_F(ModuleGdxWithStackTest, call_on_handler_protected_method) { - Mod()->call_on_handler_protected_method(handler_tid_, 1, 2, 3); -} - -TEST_F(ModuleGdxWithStackTest, test_call_on_main) { Mod()->call_on_main(mainloop_tid_, 1, 2, 3); } - -TEST_F(ModuleGdxWithStackTest, test_call_gdx_external_function_on_main) { - Mod()->call_on_main_external_function(mainloop_tid_, 1, 2.3, 'c'); -} - -TEST_F(ModuleGdxWithStackTest, test_call_on_main_repost) { - Mod()->call_on_main_repost(mainloop_tid_, 1, 2, 3); -} - -TEST_F(ModuleGdxWithStackTest, test_call_on_main_recurse) { - Mod()->call_on_main_recurse(mainloop_tid_, 1, 2, 3); -} - -TEST_F(ModuleGdxWithStackTest, test_call_on_jni) { Mod()->call_on_jni(jniloop_tid_, 1, 2, 3); } - -TEST_F(ModuleGdxWithStackTest, test_call_gdx_external_function_on_jni) { - Mod()->call_on_jni_external_function(jniloop_tid_, 1, 2.3, 'c'); -} - -TEST_F(ModuleGdxWithStackTest, test_call_on_jni_repost) { - Mod()->call_on_jni_repost(jniloop_tid_, 1, 2, 3); -} - -TEST_F(ModuleGdxWithStackTest, test_call_on_jni_recurse) { - Mod()->call_on_jni_recurse(jniloop_tid_, 1, 2, 3); -} - -class ModuleGdxWithInstrumentedCallback : public ModuleGdxWithStackTest { -protected: - void SetUp() override { ModuleGdxWithStackTest::SetUp(); } - - void TearDown() override { ModuleGdxWithStackTest::TearDown(); } - - // A helper class to promise/future for synchronization - class Promises { - public: - std::promise<std::string> result; - std::future<std::string> result_future = result.get_future(); - std::promise<void> blocking; - std::future<void> blocking_future = blocking.get_future(); - std::promise<void> unblock; - std::future<void> unblock_future = unblock.get_future(); - }; - - class InstrumentedCallback { - public: - Promises promises; - common::ContextualCallback<void(std::string)> callback; - }; - - class InstrumentedOnceCallback { - public: - Promises promises; - common::ContextualOnceCallback<void(std::string)> callback; - }; - - std::unique_ptr<InstrumentedCallback> GetNewCallbackOnMain() { - auto to_return = std::make_unique<InstrumentedCallback>(); - to_return->callback = get_main()->Bind( - [](std::promise<std::string>* promise_ptr, std::promise<void>* blocking, - std::future<void>* unblock, std::string result) { - // Tell the test that this callback is running (and blocking) - blocking->set_value(); - // Block until the test is ready to continue - ASSERT_EQ(std::future_status::ready, unblock->wait_for(std::chrono::seconds(1))); - // Send the result back to the test - promise_ptr->set_value(result); - log::info("set_value {}", result); - }, - &to_return->promises.result, &to_return->promises.blocking, - &to_return->promises.unblock_future); - - return to_return; - } - - std::unique_ptr<InstrumentedOnceCallback> GetNewOnceCallbackOnMain() { - auto to_return = std::make_unique<InstrumentedOnceCallback>(); - to_return->callback = get_main()->BindOnce( - [](std::promise<std::string>* promise_ptr, std::promise<void>* blocking, - std::future<void>* unblock, std::string result) { - blocking->set_value(); - ASSERT_EQ(std::future_status::ready, unblock->wait_for(std::chrono::seconds(1))); - promise_ptr->set_value(result); - log::info("set_value {}", result); - }, - &to_return->promises.result, &to_return->promises.blocking, - &to_return->promises.unblock_future); - - return to_return; - } -}; - -TEST_F(ModuleGdxWithInstrumentedCallback, test_call_callback_on_handler) { - auto instrumented = GetNewCallbackOnMain(); - Mod()->set_callback(instrumented->callback); - - // Enqueue the callback and wait for it to block on main thread - std::string result = "This was called on the handler"; - Mod()->call_callback_on_handler(result); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.blocking_future.wait_for(std::chrono::seconds(1))); - log::info("Waiting"); - - // Enqueue something else on the main thread and verify that it hasn't run - static auto second_task_promise = std::promise<void>(); - auto final_future = second_task_promise.get_future(); - do_in_main_thread(common::BindOnce( - [](std::promise<void> promise) { - promise.set_value(); - log::info("Finally"); - }, - std::move(second_task_promise))); - ASSERT_EQ(std::future_status::timeout, final_future.wait_for(std::chrono::milliseconds(1))); - - // Let the callback start - instrumented->promises.unblock.set_value(); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.result_future.wait_for(std::chrono::seconds(1))); - ASSERT_EQ(result, instrumented->promises.result_future.get()); - - // Let the second task finish - ASSERT_EQ(std::future_status::ready, final_future.wait_for(std::chrono::seconds(1))); -} - -TEST_F(ModuleGdxWithInstrumentedCallback, test_call_once_callback_on_handler) { - auto instrumented = GetNewOnceCallbackOnMain(); - Mod()->set_once_callback(std::move(instrumented->callback)); - - // Enqueue the callback and wait for it to block on main thread - std::string result = "This was called on the handler"; - Mod()->call_once_callback_on_handler(result); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.blocking_future.wait_for(std::chrono::seconds(1))); - log::info("Waiting"); - - // Enqueue something else on the main thread and verify that it hasn't run - static auto second_task_promise = std::promise<void>(); - auto final_future = second_task_promise.get_future(); - do_in_main_thread(common::BindOnce( - [](std::promise<void> promise) { - promise.set_value(); - log::info("Finally"); - }, - std::move(second_task_promise))); - ASSERT_EQ(std::future_status::timeout, final_future.wait_for(std::chrono::milliseconds(1))); - - // Let the callback start - instrumented->promises.unblock.set_value(); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.result_future.wait_for(std::chrono::seconds(1))); - ASSERT_EQ(result, instrumented->promises.result_future.get()); - - // Let the second task finish - ASSERT_EQ(std::future_status::ready, final_future.wait_for(std::chrono::seconds(1))); -} - -TEST_F(ModuleGdxWithInstrumentedCallback, test_call_callback_on_main) { - auto instrumented = GetNewCallbackOnMain(); - Mod()->set_callback(instrumented->callback); - - // Enqueue the callback and wait for it to block on main thread - std::string result = "This was called on the main"; - Mod()->call_callback_on_main(result); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.blocking_future.wait_for(std::chrono::seconds(1))); - log::info("Waiting"); - - // Enqueue something else on the main thread and verify that it hasn't run - static auto second_task_promise = std::promise<void>(); - auto final_future = second_task_promise.get_future(); - do_in_main_thread(common::BindOnce( - [](std::promise<void> promise) { - promise.set_value(); - log::info("Finally"); - }, - std::move(second_task_promise))); - ASSERT_EQ(std::future_status::timeout, final_future.wait_for(std::chrono::milliseconds(1))); - - // Let the callback start - instrumented->promises.unblock.set_value(); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.result_future.wait_for(std::chrono::seconds(1))); - ASSERT_EQ(result, instrumented->promises.result_future.get()); - - // Let the second task finish - ASSERT_EQ(std::future_status::ready, final_future.wait_for(std::chrono::seconds(1))); -} - -TEST_F(ModuleGdxWithInstrumentedCallback, test_call_once_callback_on_main) { - auto instrumented = GetNewOnceCallbackOnMain(); - Mod()->set_once_callback(std::move(instrumented->callback)); - - // Enqueue the callback and wait for it to block on main thread - std::string result = "This was called on the main"; - Mod()->call_once_callback_on_main(result); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.blocking_future.wait_for(std::chrono::seconds(1))); - log::info("Waiting"); - - // Enqueue something else on the main thread and verify that it hasn't run - static auto second_task_promise = std::promise<void>(); - auto final_future = second_task_promise.get_future(); - do_in_main_thread(common::BindOnce( - [](std::promise<void> promise) { - promise.set_value(); - log::info("Finally"); - }, - std::move(second_task_promise))); - ASSERT_EQ(std::future_status::timeout, final_future.wait_for(std::chrono::milliseconds(1))); - - // Let the callback start - instrumented->promises.unblock.set_value(); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.result_future.wait_for(std::chrono::seconds(1))); - ASSERT_EQ(result, instrumented->promises.result_future.get()); - - // Let the second task finish - ASSERT_EQ(std::future_status::ready, final_future.wait_for(std::chrono::seconds(1))); -} - -TEST_F(ModuleGdxWithInstrumentedCallback, test_call_callback_on_jni) { - auto instrumented = GetNewCallbackOnMain(); - Mod()->set_callback(instrumented->callback); - - // Enqueue the callback and wait for it to block on main thread - std::string result = "This was called on the jni"; - Mod()->call_callback_on_jni(result); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.blocking_future.wait_for(std::chrono::seconds(1))); - log::info("Waiting"); - - // Enqueue something else on the main thread and verify that it hasn't run - static auto second_task_promise = std::promise<void>(); - auto final_future = second_task_promise.get_future(); - do_in_main_thread(common::BindOnce( - [](std::promise<void> promise) { - promise.set_value(); - log::info("Finally"); - }, - std::move(second_task_promise))); - ASSERT_EQ(std::future_status::timeout, final_future.wait_for(std::chrono::milliseconds(1))); - - // Let the callback start - instrumented->promises.unblock.set_value(); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.result_future.wait_for(std::chrono::seconds(1))); - ASSERT_EQ(result, instrumented->promises.result_future.get()); - - // Let the second task finish - ASSERT_EQ(std::future_status::ready, final_future.wait_for(std::chrono::seconds(1))); -} - -TEST_F(ModuleGdxWithInstrumentedCallback, test_call_once_callback_on_jni) { - auto instrumented = GetNewOnceCallbackOnMain(); - Mod()->set_once_callback(std::move(instrumented->callback)); - - // Enqueue the callback and wait for it to block on main thread - std::string result = "This was called on the jni"; - Mod()->call_once_callback_on_jni(result); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.blocking_future.wait_for(std::chrono::seconds(1))); - log::info("Waiting"); - - // Enqueue something else on the main thread and verify that it hasn't run - static auto second_task_promise = std::promise<void>(); - auto final_future = second_task_promise.get_future(); - do_in_main_thread(common::BindOnce( - [](std::promise<void> promise) { - promise.set_value(); - log::info("Finally"); - }, - std::move(second_task_promise))); - ASSERT_EQ(std::future_status::timeout, final_future.wait_for(std::chrono::milliseconds(1))); - - // Let the callback start - instrumented->promises.unblock.set_value(); - ASSERT_EQ(std::future_status::ready, - instrumented->promises.result_future.wait_for(std::chrono::seconds(1))); - ASSERT_EQ(result, instrumented->promises.result_future.get()); - - // Let the second task finish - ASSERT_EQ(std::future_status::ready, final_future.wait_for(std::chrono::seconds(1))); -} diff --git a/system/gd/module_gdx_unittest.h b/system/gd/module_gdx_unittest.h deleted file mode 100644 index 6765be025e..0000000000 --- a/system/gd/module_gdx_unittest.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 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. - */ - -#include <base/callback.h> -#include <base/functional/bind.h> -#include <base/location.h> - -#include <string> - -#include "common/contextual_callback.h" -#include "module.h" -#include "module_jniloop.h" -#include "module_mainloop.h" - -using namespace bluetooth; - -void external_function(int /* a */, double /* b */, char /* c */); - -class TestGdxModule : public Module, public ModuleMainloop, public ModuleJniloop { -public: - void call_on_handler_protected_method(pid_t tid, int a, int b, int c); - void call_on_main_external_function(pid_t tid, int a, double b, char c); - void call_on_main(pid_t tid, int a, int b, int c); - void call_on_main_repost(pid_t tid, int a, int b, int c); - void call_on_main_recurse(pid_t tid, int a, int b, int c); - - void call_on_jni_external_function(pid_t tid, int a, double b, char c); - void call_on_jni(pid_t tid, int a, int b, int c); - void call_on_jni_repost(pid_t tid, int a, int b, int c); - void call_on_jni_recurse(pid_t tid, int a, int b, int c); - - void set_callback(common::ContextualCallback<void(std::string)> one_message_callback); - void set_once_callback(common::ContextualOnceCallback<void(std::string)> one_message_callback); - - void call_callback_on_handler(std::string message); - void call_once_callback_on_handler(std::string message); - void call_callback_on_jni(std::string message); - void call_once_callback_on_jni(std::string message); - void call_callback_on_main(std::string message); - void call_once_callback_on_main(std::string message); - - static const bluetooth::ModuleFactory Factory; - -protected: - void protected_method(int a, int b, int c); - void call_on_main_internal(int a, int b, int c); - void call_on_jni_internal(int a, int b, int c); - bool IsStarted() const; - - void ListDependencies(bluetooth::ModuleList* /* list */) const override {} - void Start() override; - void Stop() override; - std::string ToString() const override; - -private: - struct PrivateImpl; - std::shared_ptr<TestGdxModule::PrivateImpl> pimpl_; - - common::ContextualOnceCallback<void(std::string)> call_once_; - common::ContextualCallback<void(std::string)> call_many_; - - bool started_ = false; - - friend bluetooth::ModuleRegistry; -}; diff --git a/system/gd/module_jniloop.h b/system/gd/module_jniloop.h deleted file mode 100644 index b77aa6e322..0000000000 --- a/system/gd/module_jniloop.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 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. - */ - -#pragma once - -#include <base/callback.h> -#include <base/functional/bind.h> -#include <base/location.h> - -#include "btif/include/btif_jni_task.h" - -namespace bluetooth { - -class ModuleJniloop { -protected: - ModuleJniloop() noexcept = default; - virtual ~ModuleJniloop() = default; - ModuleJniloop(const ModuleJniloop& mod) = delete; - - // Threadsafe post onto jni loop a function with copyable arguments - template <typename Functor, typename... Args> - void PostFunctionOnJni(Functor&& functor, Args&&... args) const { - do_in_jni_thread(base::BindOnce(std::forward<Functor>(functor), std::forward<Args>(args)...)); - } - - // Threadsafe post onto jni loop a method and context with copyable arguments - template <typename T, typename Functor, typename... Args> - void PostMethodOnJni(std::shared_ptr<T> ref, Functor&& functor, Args... args) const { - do_in_jni_thread(base::BindOnce( - [](std::weak_ptr<T> ref, Functor&& functor, Args&&... args) { - if (std::shared_ptr<T> spt = ref.lock()) { - base::BindOnce(std::forward<Functor>(functor), spt, std::forward<Args>(args)...) - .Run(); - } - }, - std::weak_ptr<T>(ref), std::forward<Functor>(functor), std::forward<Args>(args)...)); - } -}; - -} // namespace bluetooth diff --git a/system/gd/module_jniloop_unittest.cc b/system/gd/module_jniloop_unittest.cc deleted file mode 100644 index 98c6b7e09d..0000000000 --- a/system/gd/module_jniloop_unittest.cc +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright 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. - */ - -#include "module_jniloop_unittest.h" - -#include <base/callback.h> -#include <base/functional/bind.h> -#include <base/location.h> -#include <base/threading/platform_thread.h> -#include <sys/syscall.h> - -#include <string> - -#include "btif/include/btif_jni_task.h" -#include "gtest/gtest.h" -#include "module.h" -#include "os/handler.h" -#include "os/thread.h" - -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -using namespace bluetooth; - -namespace { -constexpr int sync_timeout_in_ms = 3000; - -std::promise<pid_t> external_function_promise; -std::promise<pid_t> private_impl_promise; -std::promise<pid_t> protected_method_promise; - -} // namespace - -// Global function with C linkage -void external_function_jni(int /* a */, double /* b */, char /* c */) { - external_function_promise.set_value(base::PlatformThread::CurrentId()); -} - -// Module private implementation that is inaccessible externally -struct TestJniModule::PrivateImpl : public ModuleJniloop { - const int kMaxTestModuleRecurseDepth = 10; - - void privateCallableMethod(int /* a */, double /* b */, char /* c */) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - } - - void repostMethodTest(int /* a */, double /* b */, char /* c */) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - } - - void privateCallableRepostMethod(std::shared_ptr<TestJniModule::PrivateImpl> ptr, int a, double b, - char c) { - PostMethodOnJni(ptr, &PrivateImpl::repostMethodTest, a, b, c); - } - - void privateCallableRecursiveMethod(std::shared_ptr<TestJniModule::PrivateImpl> ptr, int depth, - double b, char c) { - if (depth > kMaxTestModuleRecurseDepth) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - return; - } - PostMethodOnJni(ptr, &PrivateImpl::privateCallableRecursiveMethod, ptr, depth + 1, b, c); - } -}; - -// Protected module method executed on handler -void TestJniModule::call_on_handler_protected_method(int loop_tid, int a, int b, int c) { - protected_method_promise = std::promise<pid_t>(); - auto future = protected_method_promise.get_future(); - CallOn(this, &TestJniModule::protected_method, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Global external function executed on jni loop -void TestJniModule::call_on_jni_external_function(int loop_tid, int a, double b, char c) { - external_function_promise = std::promise<pid_t>(); - auto future = external_function_promise.get_future(); - PostFunctionOnJni(&external_function_jni, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop -void TestJniModule::call_on_jni(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise<pid_t>(); - auto future = private_impl_promise.get_future(); - PostMethodOnJni(pimpl_, &TestJniModule::PrivateImpl::privateCallableMethod, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on jni loop and reposted -void TestJniModule::call_on_jni_repost(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise<pid_t>(); - auto future = private_impl_promise.get_future(); - PostMethodOnJni(pimpl_, &TestJniModule::PrivateImpl::privateCallableRepostMethod, pimpl_, a, b, - c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on jni loop recursively -void TestJniModule::call_on_jni_recurse(int loop_tid, int depth, int b, int c) { - private_impl_promise = std::promise<pid_t>(); - auto future = private_impl_promise.get_future(); - PostMethodOnJni(pimpl_, &TestJniModule::PrivateImpl::privateCallableRecursiveMethod, pimpl_, - depth, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -void TestJniModule::protected_method(int /* a */, int /* b */, int /* c */) { - protected_method_promise.set_value(base::PlatformThread::CurrentId()); -} - -bool TestJniModule::IsStarted() const { return pimpl_ != nullptr; } - -void TestJniModule::Start() { - ASSERT_FALSE(IsStarted()); - pimpl_ = std::make_shared<TestJniModule::PrivateImpl>(); -} - -void TestJniModule::Stop() { - ASSERT_TRUE(IsStarted()); - pimpl_.reset(); -} - -std::string TestJniModule::ToString() const { return std::string(__func__); } - -const bluetooth::ModuleFactory TestJniModule::Factory = - bluetooth::ModuleFactory([]() { return new TestJniModule(); }); - -// -// Module GDx Testing Below -// -class ModuleGdxJniTest : public ::testing::Test { -protected: - void SetUp() override { - test_framework_tid_ = base::PlatformThread::CurrentId(); - module_ = new TestJniModule(); - jni_thread_startup(); - jniloop_tid_ = get_jniloop_tid(); - } - - void TearDown() override { - sync_jni_handler(); - jni_thread_shutdown(); - delete module_; - } - - void sync_jni_handler() { - std::promise promise = std::promise<void>(); - std::future future = promise.get_future(); - post_on_bt_jni([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(sync_timeout_in_ms)); - } - - static pid_t get_jniloop_tid() { - std::promise<pid_t> pid_promise = std::promise<pid_t>(); - auto future = pid_promise.get_future(); - post_on_bt_jni([&pid_promise]() { pid_promise.set_value(base::PlatformThread::CurrentId()); }); - return future.get(); - } - - pid_t test_framework_tid_{-1}; - pid_t jniloop_tid_{-1}; - TestModuleRegistry module_registry_; - TestJniModule* module_; -}; - -class ModuleGdxWithJniStackTest : public ModuleGdxJniTest { -protected: - void SetUp() override { - ModuleGdxJniTest::SetUp(); - module_registry_.InjectTestModule(&TestJniModule::Factory, module_ /* pass ownership */); - module_ = nullptr; // ownership is passed - handler_tid_ = get_handler_tid(module_registry_.GetTestModuleHandler(&TestJniModule::Factory)); - } - - static pid_t get_handler_tid(os::Handler* handler) { - std::promise<pid_t> handler_tid_promise = std::promise<pid_t>(); - std::future<pid_t> future = handler_tid_promise.get_future(); - handler->Post(common::BindOnce( - [](std::promise<pid_t> promise) { - promise.set_value(base::PlatformThread::CurrentId()); - }, - std::move(handler_tid_promise))); - return future.get(); - } - - void TearDown() override { - module_registry_.StopAll(); - ModuleGdxJniTest::TearDown(); - } - - TestJniModule* Mod() { return module_registry_.GetModuleUnderTest<TestJniModule>(); } - - pid_t handler_tid_{-1}; -}; - -TEST_F(ModuleGdxJniTest, nop) {} - -TEST_F(ModuleGdxJniTest, lifecycle) { - ::bluetooth::os::Thread* thread = - new bluetooth::os::Thread("Name", bluetooth::os::Thread::Priority::REAL_TIME); - ASSERT_FALSE(module_registry_.IsStarted<TestJniModule>()); - module_registry_.Start<TestJniModule>(thread); - ASSERT_TRUE(module_registry_.IsStarted<TestJniModule>()); - module_registry_.StopAll(); - ASSERT_FALSE(module_registry_.IsStarted<TestJniModule>()); - delete thread; -} - -TEST_F(ModuleGdxWithJniStackTest, call_on_handler_protected_method) { - Mod()->call_on_handler_protected_method(handler_tid_, 1, 2, 3); -} - -TEST_F(ModuleGdxWithJniStackTest, test_call_on_jni) { Mod()->call_on_jni(jniloop_tid_, 1, 2, 3); } - -TEST_F(ModuleGdxWithJniStackTest, test_call_external_function) { - Mod()->call_on_jni_external_function(jniloop_tid_, 1, 2.3, 'c'); -} - -TEST_F(ModuleGdxWithJniStackTest, test_call_on_jni_repost) { - Mod()->call_on_jni_repost(jniloop_tid_, 1, 2, 3); -} - -TEST_F(ModuleGdxWithJniStackTest, test_call_on_jni_recurse) { - Mod()->call_on_jni_recurse(jniloop_tid_, 1, 2, 3); -} diff --git a/system/gd/module_jniloop_unittest.h b/system/gd/module_jniloop_unittest.h deleted file mode 100644 index 032606251e..0000000000 --- a/system/gd/module_jniloop_unittest.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 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. - */ - -#include <base/callback.h> -#include <base/functional/bind.h> -#include <base/location.h> - -#include <string> - -#include "module.h" -#include "module_jniloop.h" - -using namespace bluetooth; - -void external_function(int /* a */, double /* b */, char /* c */); - -class TestJniModule : public Module, public ModuleJniloop { -public: - void call_on_handler_protected_method(pid_t tid, int a, int b, int c); - void call_on_jni_external_function(pid_t tid, int a, double b, char c); - void call_on_jni(pid_t tid, int a, int b, int c); - void call_on_jni_repost(pid_t tid, int a, int b, int c); - void call_on_jni_recurse(pid_t tid, int a, int b, int c); - - static const bluetooth::ModuleFactory Factory; - -protected: - void protected_method(int a, int b, int c); - void call_on_jni_internal(int a, int b, int c); - bool IsStarted() const; - - void ListDependencies(bluetooth::ModuleList* /* list */) const override {} - void Start() override; - void Stop() override; - std::string ToString() const override; - -private: - struct PrivateImpl; - std::shared_ptr<TestJniModule::PrivateImpl> pimpl_; - - bool started_ = false; - - friend bluetooth::ModuleRegistry; -}; diff --git a/system/gd/module_mainloop.h b/system/gd/module_mainloop.h deleted file mode 100644 index 9f07e89ef6..0000000000 --- a/system/gd/module_mainloop.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 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. - */ - -#pragma once - -#include <base/callback.h> -#include <base/functional/bind.h> -#include <base/location.h> - -#include "stack/include/main_thread.h" - -namespace bluetooth { - -class ModuleMainloop { -protected: - ModuleMainloop() noexcept = default; - virtual ~ModuleMainloop() = default; - ModuleMainloop(const ModuleMainloop& mod) = delete; - - // Threadsafe post onto mainloop a function with copyable arguments - template <typename Functor, typename... Args> - void PostFunctionOnMain(Functor&& functor, Args&&... args) const { - do_in_main_thread(base::BindOnce(std::forward<Functor>(functor), std::forward<Args>(args)...)); - } - - // Threadsafe post onto mainloop a method and context with copyable arguments - template <typename T, typename Functor, typename... Args> - void PostMethodOnMain(std::shared_ptr<T> ref, Functor&& functor, Args... args) const { - do_in_main_thread(base::BindOnce( - [](std::weak_ptr<T> ref, Functor&& functor, Args&&... args) { - if (std::shared_ptr<T> spt = ref.lock()) { - base::BindOnce(std::forward<Functor>(functor), spt, std::forward<Args>(args)...) - .Run(); - } - }, - std::weak_ptr<T>(ref), std::forward<Functor>(functor), std::forward<Args>(args)...)); - } -}; - -} // namespace bluetooth diff --git a/system/gd/module_mainloop_unittest.cc b/system/gd/module_mainloop_unittest.cc deleted file mode 100644 index cac37f83fe..0000000000 --- a/system/gd/module_mainloop_unittest.cc +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright 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. - */ - -#include "module_mainloop_unittest.h" - -#include <base/callback.h> -#include <base/functional/bind.h> -#include <base/location.h> -#include <base/threading/platform_thread.h> -#include <sys/syscall.h> - -#include <string> - -#include "gtest/gtest.h" -#include "module.h" -#include "os/handler.h" -#include "os/thread.h" -#include "stack/include/main_thread.h" - -// TODO(b/369381361) Enfore -Wmissing-prototypes -#pragma GCC diagnostic ignored "-Wmissing-prototypes" - -using namespace bluetooth; - -namespace { -constexpr int sync_timeout_in_ms = 3000; - -std::promise<pid_t> external_function_promise; -std::promise<pid_t> private_impl_promise; -std::promise<pid_t> protected_method_promise; - -} // namespace - -// Global function with C linkage -void external_function_main(int /* a */, double /* b */, char /* c */) { - external_function_promise.set_value(base::PlatformThread::CurrentId()); -} - -// Module private implementation that is inaccessible externally -struct TestModule::PrivateImpl : public ModuleMainloop { - const int kMaxTestModuleRecurseDepth = 10; - - void privateCallableMethod(int /* a */, double /* b */, char /* c */) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - } - - void repostMethodTest(int /* a */, double /* b */, char /* c */) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - } - - void privateCallableRepostMethod(std::shared_ptr<TestModule::PrivateImpl> ptr, int a, double b, - char c) { - PostMethodOnMain(ptr, &PrivateImpl::repostMethodTest, a, b, c); - } - - void privateCallableRecursiveMethod(std::shared_ptr<TestModule::PrivateImpl> ptr, int depth, - double b, char c) { - if (depth > kMaxTestModuleRecurseDepth) { - private_impl_promise.set_value(base::PlatformThread::CurrentId()); - return; - } - PostMethodOnMain(ptr, &PrivateImpl::privateCallableRecursiveMethod, ptr, depth + 1, b, c); - } -}; - -// Protected module method executed on handler -void TestModule::call_on_handler_protected_method(int loop_tid, int a, int b, int c) { - protected_method_promise = std::promise<pid_t>(); - auto future = protected_method_promise.get_future(); - CallOn(this, &TestModule::protected_method, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Global external function executed on main loop -void TestModule::call_on_main_external_function(int loop_tid, int a, double b, char c) { - external_function_promise = std::promise<pid_t>(); - auto future = external_function_promise.get_future(); - PostFunctionOnMain(&external_function_main, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop -void TestModule::call_on_main(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise<pid_t>(); - auto future = private_impl_promise.get_future(); - PostMethodOnMain(pimpl_, &TestModule::PrivateImpl::privateCallableMethod, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop and reposted -void TestModule::call_on_main_repost(int loop_tid, int a, int b, int c) { - private_impl_promise = std::promise<pid_t>(); - auto future = private_impl_promise.get_future(); - PostMethodOnMain(pimpl_, &TestModule::PrivateImpl::privateCallableRepostMethod, pimpl_, a, b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -// Private implementation method executed on main loop recursively -void TestModule::call_on_main_recurse(int loop_tid, int depth, int b, int c) { - private_impl_promise = std::promise<pid_t>(); - auto future = private_impl_promise.get_future(); - PostMethodOnMain(pimpl_, &TestModule::PrivateImpl::privateCallableRecursiveMethod, pimpl_, depth, - b, c); - ASSERT_EQ(future.wait_for(std::chrono::seconds(3)), std::future_status::ready); - ASSERT_EQ(future.get(), loop_tid); -} - -void TestModule::protected_method(int /* a */, int /* b */, int /* c */) { - protected_method_promise.set_value(base::PlatformThread::CurrentId()); -} - -bool TestModule::IsStarted() const { return pimpl_ != nullptr; } - -void TestModule::Start() { - ASSERT_FALSE(IsStarted()); - pimpl_ = std::make_shared<TestModule::PrivateImpl>(); -} - -void TestModule::Stop() { - ASSERT_TRUE(IsStarted()); - pimpl_.reset(); -} - -std::string TestModule::ToString() const { return std::string(__func__); } - -const bluetooth::ModuleFactory TestModule::Factory = - bluetooth::ModuleFactory([]() { return new TestModule(); }); - -// -// Module GDx Testing Below -// -class ModuleMainGdxTest : public ::testing::Test { -protected: - void SetUp() override { - test_framework_tid_ = base::PlatformThread::CurrentId(); - module_ = new TestModule(); - main_thread_start_up(); - mainloop_tid_ = get_mainloop_tid(); - } - - void TearDown() override { - sync_main_handler(); - main_thread_shut_down(); - delete module_; - } - - void sync_main_handler() { - std::promise promise = std::promise<void>(); - std::future future = promise.get_future(); - post_on_bt_main([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(sync_timeout_in_ms)); - } - - static pid_t get_mainloop_tid() { - std::promise<pid_t> pid_promise = std::promise<pid_t>(); - auto future = pid_promise.get_future(); - post_on_bt_main([&pid_promise]() { pid_promise.set_value(base::PlatformThread::CurrentId()); }); - return future.get(); - } - - pid_t test_framework_tid_{-1}; - pid_t mainloop_tid_{-1}; - TestModuleRegistry module_registry_; - TestModule* module_; -}; - -class ModuleMainGdxWithStackTest : public ModuleMainGdxTest { -protected: - void SetUp() override { - ModuleMainGdxTest::SetUp(); - module_registry_.InjectTestModule(&TestModule::Factory, module_ /* pass ownership */); - module_ = nullptr; // ownership is passed - handler_tid_ = get_handler_tid(module_registry_.GetTestModuleHandler(&TestModule::Factory)); - } - - static pid_t get_handler_tid(os::Handler* handler) { - std::promise<pid_t> handler_tid_promise = std::promise<pid_t>(); - std::future<pid_t> future = handler_tid_promise.get_future(); - handler->Post(common::BindOnce( - [](std::promise<pid_t> promise) { - promise.set_value(base::PlatformThread::CurrentId()); - }, - std::move(handler_tid_promise))); - return future.get(); - } - - void TearDown() override { - module_registry_.StopAll(); - ModuleMainGdxTest::TearDown(); - } - - TestModule* Mod() { return module_registry_.GetModuleUnderTest<TestModule>(); } - - pid_t handler_tid_{-1}; -}; - -TEST_F(ModuleMainGdxTest, nop) {} - -TEST_F(ModuleMainGdxTest, lifecycle) { - ::bluetooth::os::Thread* thread = - new bluetooth::os::Thread("Name", bluetooth::os::Thread::Priority::REAL_TIME); - ASSERT_FALSE(module_registry_.IsStarted<TestModule>()); - module_registry_.Start<TestModule>(thread); - ASSERT_TRUE(module_registry_.IsStarted<TestModule>()); - module_registry_.StopAll(); - ASSERT_FALSE(module_registry_.IsStarted<TestModule>()); - delete thread; -} - -TEST_F(ModuleMainGdxWithStackTest, call_on_handler_protected_method) { - Mod()->call_on_handler_protected_method(handler_tid_, 1, 2, 3); -} - -TEST_F(ModuleMainGdxWithStackTest, test_call_on_main) { - Mod()->call_on_main(mainloop_tid_, 1, 2, 3); -} - -TEST_F(ModuleMainGdxWithStackTest, test_call_external_function) { - Mod()->call_on_main_external_function(mainloop_tid_, 1, 2.3, 'c'); -} - -TEST_F(ModuleMainGdxWithStackTest, test_call_on_main_repost) { - Mod()->call_on_main_repost(mainloop_tid_, 1, 2, 3); -} - -TEST_F(ModuleMainGdxWithStackTest, test_call_on_main_recurse) { - Mod()->call_on_main_recurse(mainloop_tid_, 1, 2, 3); -} diff --git a/system/gd/module_mainloop_unittest.h b/system/gd/module_mainloop_unittest.h deleted file mode 100644 index 8e864f33d7..0000000000 --- a/system/gd/module_mainloop_unittest.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 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. - */ - -#include <base/callback.h> -#include <base/functional/bind.h> -#include <base/location.h> - -#include <string> - -#include "module.h" -#include "module_mainloop.h" - -using namespace bluetooth; - -void external_function(int /* a */, double /* b */, char /* c */); - -class TestModule : public Module, public ModuleMainloop { -public: - void call_on_handler_protected_method(pid_t tid, int a, int b, int c); - void call_on_main_external_function(pid_t tid, int a, double b, char c); - void call_on_main(pid_t tid, int a, int b, int c); - void call_on_main_repost(pid_t tid, int a, int b, int c); - void call_on_main_recurse(pid_t tid, int a, int b, int c); - - static const bluetooth::ModuleFactory Factory; - -protected: - void protected_method(int a, int b, int c); - void call_on_main_internal(int a, int b, int c); - bool IsStarted() const; - - void ListDependencies(bluetooth::ModuleList* /* list */) const override {} - void Start() override; - void Stop() override; - std::string ToString() const override; - -private: - struct PrivateImpl; - std::shared_ptr<TestModule::PrivateImpl> pimpl_; - - bool started_ = false; - - friend bluetooth::ModuleRegistry; -}; diff --git a/system/gd/module_state_dumper_unittest.cc b/system/gd/module_state_dumper_unittest.cc deleted file mode 100644 index 2bb3e92add..0000000000 --- a/system/gd/module_state_dumper_unittest.cc +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 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. - */ - -#include "module_state_dumper_unittest.h" - -#include <base/callback.h> -#include <base/functional/bind.h> -#include <base/location.h> -#include <base/threading/platform_thread.h> -#include <bluetooth/log.h> -#include <sys/syscall.h> - -#include <sstream> -#include <string> - -#include "gtest/gtest.h" -#include "module_dumper.h" -#include "os/handler.h" -#include "os/thread.h" -#include "stack/include/main_thread.h" - -using namespace bluetooth; - -namespace { - -constexpr int sync_timeout_in_ms = 3000; -constexpr char title[] = "module_state_dumper_test"; - -} // namespace - -// Module private implementation that is inaccessible externally -struct StateDumperTestModule::PrivateImpl : public ModuleMainloop {}; - -bool StateDumperTestModule::IsStarted() const { return pimpl_ != nullptr; } - -void StateDumperTestModule::Start() { - ASSERT_FALSE(IsStarted()); - pimpl_ = std::make_shared<StateDumperTestModule::PrivateImpl>(); -} - -void StateDumperTestModule::Stop() { - ASSERT_TRUE(IsStarted()); - pimpl_.reset(); -} - -std::string StateDumperTestModule::ToString() const { return std::string(__func__); } - -const bluetooth::ModuleFactory StateDumperTestModule::Factory = - bluetooth::ModuleFactory([]() { return new StateDumperTestModule(); }); - -DumpsysDataFinisher StateDumperTestModule::GetDumpsysData( - flatbuffers::FlatBufferBuilder* /* builder */) const { - log::info("flatbuffers"); - return EmptyDumpsysDataFinisher; -} - -// -// Module GDx Testing Below -// -class ModuleStateDumperTest : public ::testing::Test { -protected: - void SetUp() override { - test_framework_tid_ = base::PlatformThread::CurrentId(); - module_ = new StateDumperTestModule(); - main_thread_start_up(); - mainloop_tid_ = get_mainloop_tid(); - } - - void TearDown() override { - sync_main_handler(); - main_thread_shut_down(); - delete module_; - } - - void sync_main_handler() { - std::promise promise = std::promise<void>(); - std::future future = promise.get_future(); - post_on_bt_main([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(sync_timeout_in_ms)); - } - - static pid_t get_mainloop_tid() { - std::promise<pid_t> pid_promise = std::promise<pid_t>(); - auto future = pid_promise.get_future(); - post_on_bt_main([&pid_promise]() { pid_promise.set_value(base::PlatformThread::CurrentId()); }); - return future.get(); - } - - pid_t test_framework_tid_{-1}; - pid_t mainloop_tid_{-1}; - TestModuleRegistry module_registry_; - StateDumperTestModule* module_; -}; - -class ModuleStateDumperWithStackTest : public ModuleStateDumperTest { -protected: - void SetUp() override { - ModuleStateDumperTest::SetUp(); - module_registry_.InjectTestModule(&StateDumperTestModule::Factory, - module_ /* pass ownership */); - module_ = nullptr; // ownership is passed - } - - static pid_t get_handler_tid(os::Handler* handler) { - std::promise<pid_t> handler_tid_promise = std::promise<pid_t>(); - std::future<pid_t> future = handler_tid_promise.get_future(); - handler->Post(common::BindOnce( - [](std::promise<pid_t> promise) { - promise.set_value(base::PlatformThread::CurrentId()); - }, - std::move(handler_tid_promise))); - return future.get(); - } - - void TearDown() override { - module_registry_.StopAll(); - ModuleStateDumperTest::TearDown(); - } - - StateDumperTestModule* Mod() { - return module_registry_.GetModuleUnderTest<StateDumperTestModule>(); - } - - pid_t handler_tid_{-1}; -}; - -TEST_F(ModuleStateDumperTest, lifecycle) { - ::bluetooth::os::Thread* thread = - new bluetooth::os::Thread("Name", bluetooth::os::Thread::Priority::REAL_TIME); - ASSERT_FALSE(module_registry_.IsStarted<StateDumperTestModule>()); - module_registry_.Start<StateDumperTestModule>(thread); - ASSERT_TRUE(module_registry_.IsStarted<StateDumperTestModule>()); - module_registry_.StopAll(); - ASSERT_FALSE(module_registry_.IsStarted<StateDumperTestModule>()); - delete thread; -} - -TEST_F(ModuleStateDumperWithStackTest, dump_state) { - ModuleDumper dumper(STDOUT_FILENO, module_registry_, title); - - std::string output; - std::ostringstream oss; - dumper.DumpState(&output, oss); - - log::info("DUMP STATE"); - log::info("{}", oss.str()); - log::info("{}", output); -} diff --git a/system/gd/module_state_dumper_unittest.h b/system/gd/module_state_dumper_unittest.h deleted file mode 100644 index 7c2a1e6f1c..0000000000 --- a/system/gd/module_state_dumper_unittest.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 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. - */ - -#include <memory> -#include <string> - -#include "module.h" -#include "module_mainloop.h" - -using namespace bluetooth; - -class StateDumperTestModule : public Module, public ModuleMainloop { -public: - static const bluetooth::ModuleFactory Factory; - -protected: - bool IsStarted() const; - - void ListDependencies(bluetooth::ModuleList* /* list */) const override {} - void Start() override; - void Stop() override; - std::string ToString() const override; - - DumpsysDataFinisher GetDumpsysData(flatbuffers::FlatBufferBuilder* builder) const override; - -private: - struct PrivateImpl; - std::shared_ptr<StateDumperTestModule::PrivateImpl> pimpl_; - - bool started_ = false; - - friend bluetooth::ModuleRegistry; -}; diff --git a/system/gd/rust/topshim/facade/Android.bp b/system/gd/rust/topshim/facade/Android.bp index cfecd4465b..725ddaa355 100644 --- a/system/gd/rust/topshim/facade/Android.bp +++ b/system/gd/rust/topshim/facade/Android.bp @@ -38,7 +38,6 @@ rust_defaults { "lib-bt-packets-base", "libFraunhoferAAC", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_gd", // Gabeldorsche diff --git a/system/main/Android.bp b/system/main/Android.bp index 454dd79400..cfa85eea7e 100644 --- a/system/main/Android.bp +++ b/system/main/Android.bp @@ -192,14 +192,12 @@ cc_test { "shim/utils.cc", "test/common_stack_test.cc", "test/main_shim_dumpsys_test.cc", - "test/main_shim_stack_lifecycle_test.cc", "test/main_shim_test.cc", ], static_libs: [ "bluetooth_flags_c_lib_for_test", "libbase", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_core_rs_bridge", "libbluetooth_crypto_toolbox", @@ -241,105 +239,3 @@ cc_test { min_sdk_version: "Tiramisu", header_libs: ["libbluetooth_headers"], } - -cc_test { - name: "net_test_main_dumpsys", - test_suites: ["general-tests"], - host_supported: true, - test_options: { - unit_test: true, - }, - defaults: [ - "fluoride_defaults", - "mts_defaults", - ], - include_dirs: [ - "packages/modules/Bluetooth/system", - "packages/modules/Bluetooth/system/gd", - "packages/modules/Bluetooth/system/stack/btm", - "packages/modules/Bluetooth/system/stack/include", - ], - generated_headers: [ - "BluetoothGeneratedBundlerSchema_h_bfbs", - "BluetoothGeneratedDumpsysDataSchema_h", - ], - srcs: [ - ":BluetoothOsSources_host", - ":BluetoothStackManagerSources", - ":LibBluetoothShimSources", - ":TestCommonMainHandler", - ":TestCommonMockFunctions", - ":TestMockBta", - ":TestMockBtif", - ":TestMockBtu", - ":TestMockJni", - ":TestMockLegacyHciCommands", - ":TestMockLegacyHciInterface", - ":TestMockStack", - ":TestMockStackRnr", - "test/main_shim_stack_dumpsys_test.cc", - ], - static_libs: [ - "bluetooth_flags_c_lib_for_test", - "libbase", - "libbluetooth-dumpsys", - "libbluetooth-gdx", - "libbluetooth-types", - "libbluetooth_core_rs_bridge", - "libbluetooth_crypto_toolbox", - "libbluetooth_gd", - "libbluetooth_hci_pdl", - "libbluetooth_log", - "libbt-common", - "libbt-platform-protos-lite", - "libbtdevice", - "libchrome", - "libcom.android.sysprop.bluetooth.wrapped", - "libevent", - "libflatbuffers-cpp", - "libgmock", - "liblog", - "libosi", - ], - shared_libs: [ - "libPlatformProperties", - "libaconfig_storage_read_api_cc", - "libcrypto", - "server_configurable_flags", - ], - target: { - linux: { - srcs: [ - ":BluetoothOsSources_fake_timer", - ], - }, - android: { - static_libs: [ - "android.hardware.bluetooth@1.0", - "android.hardware.bluetooth@1.1", - "android.system.suspend-V1-ndk", - "android.system.suspend.control-V1-ndk", - "libstatslog_bt", - ], - shared_libs: [ - "libbinder_ndk", - "libcutils", - "libhidlbase", - "libstatssocket", - "libutils", - ], - }, - }, - sanitize: { - address: true, - all_undefined: true, - cfi: true, - integer_overflow: true, - scs: true, - diag: { - undefined: true, - }, - }, - min_sdk_version: "Tiramisu", - header_libs: ["libbluetooth_headers"], -} diff --git a/system/main/test/main_shim_stack_dumpsys_test.cc b/system/main/test/main_shim_stack_dumpsys_test.cc deleted file mode 100644 index 30e6df1225..0000000000 --- a/system/main/test/main_shim_stack_dumpsys_test.cc +++ /dev/null @@ -1,643 +0,0 @@ -/* - * Copyright 2024 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. - */ - -#include <bluetooth/log.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> -#include <unistd.h> - -#include <cstdlib> -#include <memory> - -#include "common/circular_buffer.h" -#include "common/strings.h" -#include "gd/module_jniloop.h" -#include "gd/module_mainloop.h" -#include "hci/include/packet_fragmenter.h" -#include "main/shim/dumpsys.h" -#include "main/shim/entry.h" -#include "main/shim/stack.h" -#include "module.h" -#include "os/thread.h" -#include "shim/dumpsys.h" -#include "stack/btm/btm_int_types.h" -#include "stack/btm/btm_sec_cb.h" -#include "stack/include/main_thread.h" -#include "test/mock/mock_main_shim_entry.h" - -using ::testing::_; - -using namespace bluetooth; -using namespace testing; - -tBTM_CB btm_cb{}; // main::shim::le_scanning_manager -tBTM_SEC_CB btm_sec_cb{}; // main::shim::acl - -const packet_fragmenter_t* packet_fragmenter_get_interface() { - return nullptr; -} // main::shim::hci_layer -bluetooth::common::TimestamperInMilliseconds - timestamper_in_milliseconds; // main::shim::le_scanning_manager - -namespace { -constexpr char kLogTagStopped[] = "STOPPED"; -constexpr char kLogTagStarting[] = "STARTING"; -constexpr char kLogTagStarted[] = "STARTED"; -constexpr char kLogTagQuiescing[] = "QUIESCING"; -constexpr char kLogTagQuiesced[] = "QUIESCED"; - -constexpr char kTestStackThreadName[] = "test_stack_thread"; -constexpr int kSyncMainLoopTimeoutMs = 3000; -constexpr int kWaitUntilHandlerStoppedMs = 2000; -constexpr size_t kNumTestClients = 10; - -constexpr size_t kTagLength = 48 + sizeof(' ') + sizeof(' '); -inline void log_tag(std::string tag) { - std::string prepend(kTagLength / 2 - tag.size() / 2, '='); - std::string append(kTagLength / 2 - tag.size() / 2, '='); - log::info("{} {} {}", prepend, tag, append); -} - -class MainThread { -public: - MainThread() { - main_thread_start_up(); - post_on_bt_main([]() { log::info("<=== tid Main loop started"); }); - } - - ~MainThread() { - sync_main_handler(); - main_thread_shut_down(); - } - -private: - void sync_main_handler() { - std::promise promise = std::promise<void>(); - std::future future = promise.get_future(); - post_on_bt_main([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(kSyncMainLoopTimeoutMs)); - } -}; - -class TestStackManager { -public: - TestStackManager() { - // Stack manager is started in the test after each test uses the default - // or adds their own modules - } - - ~TestStackManager() { - log::debug("Deleting stack manager"); - Stop(); - } - - TestStackManager(const TestStackManager&) = delete; - - template <typename T> - void AddModule() { - modules_.add<T>(); - } - - void Start() { - if (stack_started_) { - return; - } - log::info("Starting up stack manager"); - stack_started_ = true; - bluetooth::os::Thread* stack_thread = new bluetooth::os::Thread( - kTestStackThreadName, bluetooth::os::Thread::Priority::NORMAL); - bluetooth::shim::Stack::GetInstance()->StartModuleStack(&modules_, stack_thread); - bluetooth::shim::Stack::GetInstance()->GetHandler()->Call( - []() { log::info("<=== tid GD Event loop started"); }); - } - - void Stop() { - if (!stack_started_) { - return; - } - stack_started_ = false; - bluetooth::shim::Stack::GetInstance()->Stop(); - } - - // NOTE: Stack manager *must* be active else method returns nullptr - // if stack manager has not started or shutdown - template <typename T> - static T* GetUnsafeModule() { - return bluetooth::shim::Stack::GetInstance()->GetStackManager()->GetInstance<T>(); - } - - size_t NumModules() const { return modules_.NumModules(); } - -private: - bluetooth::ModuleList modules_; - bool stack_started_{false}; -}; - -// Data returned via callback from a stack managed module -struct TestCallbackData { - int iter; - std::string tag; -}; - -// Data sent to a stack managed module via a module API -struct TestData { - int iter; - std::string tag; - std::function<void(TestCallbackData callback_data)> callback; -}; - -} // namespace - -class TestStackDumpsysBase : public bluetooth::Module, public ModuleMainloop, public ModuleJniloop { -public: - TestStackDumpsysBase(const TestStackDumpsysBase&) = delete; - TestStackDumpsysBase& operator=(const TestStackDumpsysBase&) = delete; - - virtual ~TestStackDumpsysBase() {} - static const ModuleFactory Factory; - - virtual void TestMethod(TestData test_data) const { - log::info("Test base class iter:{} tag:{}", test_data.iter, test_data.tag); - } - -protected: - void ListDependencies(ModuleList* /* list */) const override {} - void Start() override { log::error("Started TestStackDumpsysBase"); } - void Stop() override { log::error("Stopped TestStackDumpsysBase"); } - std::string ToString() const override { return std::string("TestFunction"); } - - TestStackDumpsysBase() = default; -}; - -struct StackRunningData { - std::function<void(bool is_running)> cb; -}; - -class TestStackDumpsys1 : public TestStackDumpsysBase { -public: - TestStackDumpsys1(const TestStackDumpsys1&) = delete; - TestStackDumpsys1& operator=(const TestStackDumpsys1&) = delete; - virtual ~TestStackDumpsys1() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override; - void IsStackRunning(StackRunningData stack_running_data) const; - -private: - struct impl; - std::shared_ptr<impl> impl_; - TestStackDumpsys1(); -}; - -struct TestStackDumpsys1::impl : public ModuleMainloop, public ModuleJniloop { - void test(TestData test_data) { - TestCallbackData callback_data{ - .iter = test_data.iter, - .tag = std::string(__func__), - }; - PostFunctionOnMain([](std::function<void(TestCallbackData callback_data)> callback, - TestCallbackData data) { callback(data); }, - test_data.callback, callback_data); - } - void is_stack_running(StackRunningData stack_running_data) const { - bool is_running = bluetooth::shim::Stack::GetInstance()->IsRunning(); - if (stack_running_data.cb) { - stack_running_data.cb(is_running); - } - } -}; - -TestStackDumpsys1::TestStackDumpsys1() : TestStackDumpsysBase() { - impl_ = std::make_shared<impl>(); -} - -void TestStackDumpsys1::TestMethod(TestData test_data) const { - PostMethodOnMain(impl_, &impl::test, test_data); -} - -void TestStackDumpsys1::IsStackRunning(StackRunningData stack_running_data) const { - GetHandler()->CallOn(impl_.get(), &impl::is_stack_running, stack_running_data); -} - -class TestStackDumpsys2 : public TestStackDumpsysBase { -public: - TestStackDumpsys2(const TestStackDumpsys2&) = delete; - TestStackDumpsys2& operator=(const TestStackDumpsys2&) = delete; - virtual ~TestStackDumpsys2() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override; - -private: - struct impl; - std::shared_ptr<impl> impl_; - TestStackDumpsys2(); -}; - -struct TestStackDumpsys2::impl : public ModuleMainloop, public ModuleJniloop { - void test(TestData test_data) { - TestCallbackData callback_data{ - .iter = test_data.iter, - .tag = std::string(__func__), - }; - PostFunctionOnMain([](std::function<void(TestCallbackData callback_data)> callback, - TestCallbackData data) { callback(data); }, - test_data.callback, callback_data); - } -}; - -TestStackDumpsys2::TestStackDumpsys2() : TestStackDumpsysBase() { - impl_ = std::make_shared<impl>(); -} - -void TestStackDumpsys2::TestMethod(TestData test_data) const { - PostMethodOnMain(impl_, &impl::test, test_data); -} - -class TestStackDumpsys3 : public TestStackDumpsysBase { -public: - TestStackDumpsys3(const TestStackDumpsys3&) = delete; - TestStackDumpsys3& operator=(const TestStackDumpsys3&) = delete; - virtual ~TestStackDumpsys3() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override; - -private: - struct impl; - std::shared_ptr<impl> impl_; - TestStackDumpsys3(); -}; - -struct TestStackDumpsys3::impl : public ModuleMainloop, public ModuleJniloop { - void test(TestData test_data) { - TestCallbackData callback_data{ - .iter = test_data.iter, - .tag = std::string(__func__), - }; - PostFunctionOnMain([](std::function<void(TestCallbackData callback_data)> callback, - TestCallbackData data) { callback(data); }, - test_data.callback, callback_data); - } -}; - -TestStackDumpsys3::TestStackDumpsys3() : TestStackDumpsysBase() { - impl_ = std::make_shared<impl>(); -} - -void TestStackDumpsys3::TestMethod(TestData test_data) const { - PostMethodOnMain(impl_, &impl::test, test_data); -} - -class TestStackDumpsys4 : public TestStackDumpsysBase { -public: - TestStackDumpsys4(const TestStackDumpsys4&) = delete; - TestStackDumpsys4& operator=(const TestStackDumpsys3&) = delete; - virtual ~TestStackDumpsys4() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override { - log::info("mod:{} iter:{} tag:{}", __func__, test_data.iter, test_data.tag); - } - -private: - struct impl; - std::shared_ptr<impl> impl_; - TestStackDumpsys4() : TestStackDumpsysBase() {} -}; - -struct TestStackDumpsys4::impl : public ModuleMainloop, public ModuleJniloop {}; - -const ModuleFactory TestStackDumpsysBase::Factory = - ModuleFactory([]() { return new TestStackDumpsysBase(); }); - -const ModuleFactory TestStackDumpsys1::Factory = - ModuleFactory([]() { return new TestStackDumpsys1(); }); -const ModuleFactory TestStackDumpsys2::Factory = - ModuleFactory([]() { return new TestStackDumpsys2(); }); -const ModuleFactory TestStackDumpsys3::Factory = - ModuleFactory([]() { return new TestStackDumpsys3(); }); -const ModuleFactory TestStackDumpsys4::Factory = - ModuleFactory([]() { return new TestStackDumpsys4(); }); - -class StackWithMainThreadUnitTest : public ::testing::Test { -protected: - void SetUp() override { main_thread_ = std::make_unique<MainThread>(); } - void TearDown() override { main_thread_.reset(); } - -private: - std::unique_ptr<MainThread> main_thread_; -}; - -class StackLifecycleUnitTest : public StackWithMainThreadUnitTest { -public: - std::shared_ptr<TestStackManager> StackManager() const { return stack_manager_; } - -protected: - void SetUp() override { - StackWithMainThreadUnitTest::SetUp(); - stack_manager_ = std::make_shared<TestStackManager>(); - } - - void TearDown() override { - stack_manager_.reset(); - StackWithMainThreadUnitTest::TearDown(); - } - -private: - std::shared_ptr<TestStackManager> stack_manager_; -}; - -class MainShimStackDumpsysTest : public StackLifecycleUnitTest { -protected: - void SetUp() override { - StackLifecycleUnitTest::SetUp(); - StackManager()->AddModule<TestStackDumpsys1>(); - StackManager()->AddModule<TestStackDumpsys2>(); - StackManager()->AddModule<TestStackDumpsys3>(); - StackManager()->AddModule<bluetooth::shim::Dumpsys>(); - StackManager()->Start(); - ASSERT_EQ(4U, StackManager()->NumModules()); - - bluetooth::shim::RegisterDumpsysFunction( - (void*)this, [](int fd) { log::info("Callback to dump legacy data fd:{}", fd); }); - } - - void TearDown() override { - bluetooth::shim::UnregisterDumpsysFunction((void*)this); - StackLifecycleUnitTest::TearDown(); - } -}; - -struct CallablePostCnt { - size_t success{0}; - size_t misses{0}; - CallablePostCnt operator+=(const CallablePostCnt& post_cnt) { - return CallablePostCnt({success += post_cnt.success, misses += post_cnt.misses}); - } -}; - -// Provide a client user of the stack manager module services -class Client { -public: - Client(int id) : id_(id) {} - Client(const Client&) = default; - virtual ~Client() = default; - - // Start up the client a thread and handler - void Start() { - thread_ = new os::Thread(common::StringFormat("ClientThread%d", id_), - os::Thread::Priority::NORMAL); - handler_ = new os::Handler(thread_); - handler_->Post( - common::BindOnce([](int id) { log::info("<=== tid Started client id:{}", id); }, id_)); - } - - // Ensure all the client handlers are running - void Await() { - std::promise<void> promise; - std::future future = promise.get_future(); - handler_->Post(base::BindOnce([](std::promise<void> promise) { promise.set_value(); }, - std::move(promise))); - future.wait(); - } - - // Post a work task on behalf of this client - void Post(common::OnceClosure closure) { - if (quiesced_) { - post_cnt_.misses++; - } else { - post_cnt_.success++; - handler_->Post(std::move(closure)); - } - } - - // Safely prevent new work tasks from being posted - void Quiesce() { - if (quiesced_) { - return; - } - quiesced_ = true; - std::promise promise = std::promise<void>(); - std::future future = promise.get_future(); - handler_->Post(common::BindOnce( - [](std::promise<void> promise, int id) { - promise.set_value(); - log::info("<=== tid Quiesced client id:{}", id); - }, - std::move(promise), id_)); - future.wait_for(std::chrono::milliseconds(kSyncMainLoopTimeoutMs)); - } - - // Queisces if needed and stops the client then releases associated resources - void Stop() { - if (!quiesced_) { - Quiesce(); - } - handler_->Clear(); - handler_->WaitUntilStopped(std::chrono::milliseconds(kWaitUntilHandlerStoppedMs)); - delete handler_; - delete thread_; - } - - int Id() const { return id_; } - - CallablePostCnt GetCallablePostCnt() const { return post_cnt_; } - - std::string Name() const { return common::StringFormat("%s%d", __func__, id_); } - -private: - int id_{0}; - CallablePostCnt post_cnt_{}; - bool quiesced_{false}; - os::Handler* handler_{nullptr}; - os::Thread* thread_{nullptr}; -}; - -// Convenience object to handle multiple clients with logging -class ClientGroup { -public: - explicit ClientGroup(size_t num_clients) { - for (size_t i = 0; i < num_clients; i++) { - clients_.emplace_back(std::make_unique<Client>(i)); - } - } - - void Start() { - log_tag(kLogTagStarting); - for (auto& c : clients_) { - c->Start(); - } - } - - void Await() { - for (auto& c : clients_) { - c->Await(); - } - log_tag(kLogTagStarted); - } - - void Quiesce() { - log_tag(kLogTagQuiescing); - for (auto& c : clients_) { - c->Quiesce(); - } - log_tag(kLogTagQuiesced); - } - - void Stop() { - for (auto& c : clients_) { - c->Stop(); - } - log_tag(kLogTagStopped); - } - - void Dump() const { - for (auto& c : clients_) { - log::info("Callable post cnt client_id:{} success:{} misses:{}", c->Id(), - c->GetCallablePostCnt().success, c->GetCallablePostCnt().misses); - } - } - - CallablePostCnt GetCallablePostCnt() const { - CallablePostCnt post_cnt{}; - for (auto& c : clients_) { - post_cnt += c->GetCallablePostCnt(); - } - return post_cnt; - } - - size_t NumClients() const { return clients_.size(); } - - std::vector<std::unique_ptr<Client>> clients_; -}; - -class MainShimStackDumpsysWithClientsTest : public MainShimStackDumpsysTest { -protected: - void SetUp() override { - MainShimStackDumpsysTest::SetUp(); - client_group_.Start(); - client_group_.Await(); - } - - void TearDown() override { - client_group_.Quiesce(); - client_group_.Stop(); - MainShimStackDumpsysTest::TearDown(); - } - ClientGroup client_group_ = ClientGroup(kNumTestClients); -}; - -TEST_F(MainShimStackDumpsysWithClientsTest, all_clients_check_stack_running) { - StackRunningData stack_running_data = { - .cb = - [](bool is_stack_running) { - log::info("Stack is running:{}", (is_stack_running) ? 'T' : 'F'); - }, - }; - - // Ensure the dumpsys instance is included within the stack - ASSERT_NE(nullptr, bluetooth::shim::GetDumpsys()); - - for (auto& c : client_group_.clients_) { - c->Post(base::BindOnce( - [](StackRunningData stack_running_data) { - bluetooth::shim::Stack::GetInstance() - ->GetStackManager() - ->GetInstance<TestStackDumpsys1>() - ->IsStackRunning(stack_running_data); - }, - stack_running_data)); - } -} - -TEST_F(MainShimStackDumpsysWithClientsTest, all_clients_check_stack_running_with_iterations) { - StackRunningData stack_running_data = { - .cb = - [](bool is_stack_running) { - log::info("Run on mainloop: Stack is running:{}", - (is_stack_running) ? 'T' : 'F'); - }, - }; - - // Ensure the dumpsys instance is included within the stack - ASSERT_NE(nullptr, bluetooth::shim::GetDumpsys()); - - for (int i = 0; i < 2; i++) { - log::info("Iteration:{}", i); - for (auto& c : client_group_.clients_) { - c->Post(base::BindOnce( - [](StackRunningData stack_running_data) { - bluetooth::shim::Stack::GetInstance() - ->GetStackManager() - ->GetInstance<TestStackDumpsys1>() - ->IsStackRunning(stack_running_data); - }, - stack_running_data)); - } - } -} - -TEST_F(MainShimStackDumpsysWithClientsTest, dumpsys_single_client) { - // Ensure the dumpsys instance is included within the stack - ASSERT_NE(nullptr, bluetooth::shim::GetDumpsys()); - - const int fd = 1; - client_group_.clients_[0]->Post( - base::BindOnce([](int fd) { bluetooth::shim::Dump(fd, nullptr); }, fd)); -} - -TEST_F(MainShimStackDumpsysWithClientsTest, dumpsys_single_client_with_running_check) { - StackRunningData stack_running_data = { - .cb = - [](bool is_stack_running) { - log::info("Stack is running:{}", (is_stack_running) ? 'T' : 'F'); - }, - }; - - // Ensure the dumpsys instance is included within the stack - ASSERT_NE(nullptr, bluetooth::shim::GetDumpsys()); - - const int fd = 1; - client_group_.clients_[0]->Post(base::BindOnce( - [](StackRunningData stack_running_data) { - bluetooth::shim::Stack::GetInstance() - ->GetStackManager() - ->GetInstance<TestStackDumpsys1>() - ->IsStackRunning(stack_running_data); - }, - stack_running_data)); - client_group_.clients_[0]->Post( - base::BindOnce([](int fd) { bluetooth::shim::Dump(fd, nullptr); }, fd)); -} - -TEST_F(MainShimStackDumpsysWithClientsTest, dumpsys_many_clients) { - StackRunningData stack_running_data = { - .cb = - [](bool is_stack_running) { - log::info("Stack is running:{}", (is_stack_running) ? 'T' : 'F'); - }, - }; - - const int fd = 1; - for (auto& c : client_group_.clients_) { - c->Post(base::BindOnce([](int fd) { bluetooth::shim::Dump(fd, nullptr); }, fd)); - } -} diff --git a/system/main/test/main_shim_stack_lifecycle_test.cc b/system/main/test/main_shim_stack_lifecycle_test.cc deleted file mode 100644 index 1720574218..0000000000 --- a/system/main/test/main_shim_stack_lifecycle_test.cc +++ /dev/null @@ -1,619 +0,0 @@ -/* - * Copyright 2024 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. - */ - -#include <bluetooth/log.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> -#include <unistd.h> - -#include <atomic> -#include <cstdlib> -#include <memory> -#include <thread> - -#include "common/strings.h" -#include "gd/module_jniloop.h" -#include "gd/module_mainloop.h" -#include "main/shim/stack.h" -#include "module.h" -#include "os/thread.h" -#include "stack/include/main_thread.h" -#include "test/mock/mock_main_shim_entry.h" - -using ::testing::_; - -using namespace bluetooth; -using namespace testing; - -namespace { -constexpr int kSyncMainLoopTimeoutMs = 3000; -constexpr int kWaitUntilHandlerStoppedMs = 2000; -constexpr size_t kNumTestClients = 3; -constexpr size_t kNumTestModules = 3; -constexpr int kNumIters = 100; -constexpr int kAbruptStackShutdownIter = kNumIters * 3 / 4; -constexpr char kTestStackThreadName[] = "test_stack_thread"; -constexpr char kTestDataTag[] = "This is a test"; - -inline void maybe_yield() { - if (std::rand() & 1) { - std::this_thread::yield(); - } -} - -constexpr size_t kTagLength = 48 + sizeof(' ') + sizeof(' '); -inline void log_tag(std::string tag) { - std::string prepend(kTagLength / 2 - tag.size() / 2, '='); - std::string append(kTagLength / 2 - tag.size() / 2, '='); - log::info("{} {} {}", prepend, tag, append); -} - -class MainThread { -public: - MainThread() { main_thread_start_up(); } - - ~MainThread() { - sync_main_handler(); - main_thread_shut_down(); - } - -private: - void sync_main_handler() { - std::promise promise = std::promise<void>(); - std::future future = promise.get_future(); - post_on_bt_main([&promise]() { promise.set_value(); }); - future.wait_for(std::chrono::milliseconds(kSyncMainLoopTimeoutMs)); - } -}; - -class TestStackManager { -public: - TestStackManager() { - // Start is executed by the test after each test adds the default - // or their own modules - } - - ~TestStackManager() { - log::debug("Deleting stack manager"); - Stop(); - } - - TestStackManager(const TestStackManager&) = delete; - - template <typename T> - void AddModule() { - modules_.add<T>(); - } - - void Start() { - if (stack_started_) { - return; - } - log::info("Started stack manager"); - stack_started_ = true; - bluetooth::os::Thread* stack_thread = new bluetooth::os::Thread( - kTestStackThreadName, bluetooth::os::Thread::Priority::NORMAL); - bluetooth::shim::Stack::GetInstance()->StartModuleStack(&modules_, stack_thread); - } - - void Stop() { - if (!stack_started_) { - return; - } - stack_started_ = false; - bluetooth::shim::Stack::GetInstance()->Stop(); - } - - // NOTE: Stack manager *must* be active else method returns nullptr - // if stack manager has not started or shutdown - template <typename T> - static T* GetUnsafeModule() { - return bluetooth::shim::Stack::GetInstance()->GetStackManager()->GetInstance<T>(); - } - - size_t NumModules() const { return modules_.NumModules(); } - -private: - bluetooth::ModuleList modules_; - bool stack_started_{false}; -}; - -// Data returned via callback from a stack managed module -struct TestCallbackData { - int iter; - std::string tag; -}; - -// Data sent to a stack managed module via a module API -struct TestData { - int iter; - std::string tag; - std::function<void(TestCallbackData callback_data)> callback; -}; - -class TestStackModuleBase : public bluetooth::Module, public ModuleMainloop, public ModuleJniloop { -public: - TestStackModuleBase(const TestStackModuleBase&) = delete; - TestStackModuleBase& operator=(const TestStackModuleBase&) = delete; - - virtual ~TestStackModuleBase() {} - static const ModuleFactory Factory; - - virtual void TestMethod(TestData test_data) const { - log::info("Test base class iter:{} tag:{}", test_data.iter, test_data.tag); - } - -protected: - void ListDependencies(ModuleList* /*list*/) const override {} - void Start() override { log::error("Started TestStackModuleBase"); } - void Stop() override { log::error("Stopped TestStackModuleBase"); } - std::string ToString() const override { return std::string("TestFunction"); } - - TestStackModuleBase() = default; -}; - -class TestStackModule1 : public TestStackModuleBase { -public: - TestStackModule1(const TestStackModule1&) = delete; - TestStackModule1& operator=(const TestStackModule1&) = delete; - virtual ~TestStackModule1() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override; - -private: - struct impl; - std::shared_ptr<impl> impl_; - TestStackModule1(); -}; - -struct TestStackModule1::impl : public ModuleMainloop, public ModuleJniloop { - void test(TestData test_data) { - TestCallbackData callback_data{ - .iter = test_data.iter, - .tag = std::string(__func__), - }; - PostFunctionOnMain([](std::function<void(TestCallbackData callback_data)> callback, - TestCallbackData data) { callback(data); }, - test_data.callback, callback_data); - } -}; - -TestStackModule1::TestStackModule1() : TestStackModuleBase() { impl_ = std::make_shared<impl>(); } - -void TestStackModule1::TestMethod(TestData test_data) const { - PostMethodOnMain(impl_, &impl::test, test_data); -} - -class TestStackModule2 : public TestStackModuleBase { -public: - TestStackModule2(const TestStackModule2&) = delete; - TestStackModule2& operator=(const TestStackModule2&) = delete; - virtual ~TestStackModule2() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override; - -private: - struct impl; - std::shared_ptr<impl> impl_; - TestStackModule2(); -}; - -struct TestStackModule2::impl : public ModuleMainloop, public ModuleJniloop { - void test(TestData test_data) { - TestCallbackData callback_data{ - .iter = test_data.iter, - .tag = std::string(__func__), - }; - PostFunctionOnMain([](std::function<void(TestCallbackData callback_data)> callback, - TestCallbackData data) { callback(data); }, - test_data.callback, callback_data); - } -}; - -TestStackModule2::TestStackModule2() : TestStackModuleBase() { impl_ = std::make_shared<impl>(); } - -void TestStackModule2::TestMethod(TestData test_data) const { - PostMethodOnMain(impl_, &impl::test, test_data); -} - -class TestStackModule3 : public TestStackModuleBase { -public: - TestStackModule3(const TestStackModule3&) = delete; - TestStackModule3& operator=(const TestStackModule3&) = delete; - virtual ~TestStackModule3() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override; - -private: - struct impl; - std::shared_ptr<impl> impl_; - TestStackModule3(); -}; - -struct TestStackModule3::impl : public ModuleMainloop, public ModuleJniloop { - void test(TestData test_data) { - TestCallbackData callback_data{ - .iter = test_data.iter, - .tag = std::string(__func__), - }; - PostFunctionOnMain([](std::function<void(TestCallbackData callback_data)> callback, - TestCallbackData data) { callback(data); }, - test_data.callback, callback_data); - } -}; - -TestStackModule3::TestStackModule3() : TestStackModuleBase() { impl_ = std::make_shared<impl>(); } - -void TestStackModule3::TestMethod(TestData test_data) const { - PostMethodOnMain(impl_, &impl::test, test_data); -} - -class TestStackModule4 : public TestStackModuleBase { -public: - TestStackModule4(const TestStackModule4&) = delete; - TestStackModule4& operator=(const TestStackModule3&) = delete; - virtual ~TestStackModule4() = default; - - static const ModuleFactory Factory; - - void TestMethod(TestData test_data) const override { - log::info("mod:{} iter:{} tag:{}", __func__, test_data.iter, test_data.tag); - } - -private: - struct impl; - std::shared_ptr<impl> impl_; - TestStackModule4() : TestStackModuleBase() {} -}; - -struct TestStackModule4::impl : public ModuleMainloop, public ModuleJniloop {}; - -} // namespace - -const ModuleFactory TestStackModuleBase::Factory = - ModuleFactory([]() { return new TestStackModuleBase(); }); - -const ModuleFactory TestStackModule1::Factory = - ModuleFactory([]() { return new TestStackModule1(); }); -const ModuleFactory TestStackModule2::Factory = - ModuleFactory([]() { return new TestStackModule2(); }); -const ModuleFactory TestStackModule3::Factory = - ModuleFactory([]() { return new TestStackModule3(); }); -const ModuleFactory TestStackModule4::Factory = - ModuleFactory([]() { return new TestStackModule4(); }); - -class StackWithMainThreadUnitTest : public ::testing::Test { -protected: - void SetUp() override { main_thread_ = std::make_unique<MainThread>(); } - void TearDown() override { main_thread_.reset(); } - -private: - std::unique_ptr<MainThread> main_thread_; -}; - -class StackLifecycleUnitTest : public StackWithMainThreadUnitTest { -public: - std::shared_ptr<TestStackManager> StackManager() const { return stack_manager_; } - -protected: - void SetUp() override { - StackWithMainThreadUnitTest::SetUp(); - stack_manager_ = std::make_shared<TestStackManager>(); - } - - void TearDown() override { - stack_manager_.reset(); - StackWithMainThreadUnitTest::TearDown(); - } - -private: - std::shared_ptr<TestStackManager> stack_manager_; -}; - -TEST_F(StackLifecycleUnitTest, no_modules_in_stack) { ASSERT_EQ(0U, StackManager()->NumModules()); } - -class StackLifecycleWithDefaultModulesUnitTest : public StackLifecycleUnitTest { -protected: - void SetUp() override { - StackLifecycleUnitTest::SetUp(); - StackManager()->AddModule<TestStackModule1>(); - StackManager()->AddModule<TestStackModule2>(); - StackManager()->AddModule<TestStackModule3>(); - StackManager()->Start(); - ASSERT_EQ(3U, StackManager()->NumModules()); - } - - void TearDown() override { StackLifecycleUnitTest::TearDown(); } -}; - -struct CallablePostCnt { - size_t success{0}; - size_t misses{0}; - CallablePostCnt operator+=(const CallablePostCnt& post_cnt) { - return CallablePostCnt({success += post_cnt.success, misses += post_cnt.misses}); - } -}; - -// Provide a client user of the stack manager module services -class Client { -public: - Client(int id) : id_(id) {} - Client(const Client&) = default; - virtual ~Client() = default; - - // Start up the client a thread and handler - void Start() { - log::info("Started client {}", id_); - thread_ = new os::Thread(common::StringFormat("ClientThread%d", id_), - os::Thread::Priority::NORMAL); - handler_ = new os::Handler(thread_); - handler_->Post(common::BindOnce([](int id) { log::info("Started client {}", id); }, id_)); - } - - // Ensure all the client handlers are running - void Await() { - std::promise<void> promise; - std::future future = promise.get_future(); - handler_->Post(base::BindOnce([](std::promise<void> promise) { promise.set_value(); }, - std::move(promise))); - future.wait(); - } - - // Post a work task on behalf of this client - void Post(common::OnceClosure closure) { - if (quiesced_) { - post_cnt_.misses++; - maybe_yield(); - } else { - post_cnt_.success++; - handler_->Post(std::move(closure)); - maybe_yield(); - } - } - - // Safely prevent new work tasks from being posted - void Quiesce() { - if (quiesced_) { - return; - } - quiesced_ = true; - std::promise promise = std::promise<void>(); - std::future future = promise.get_future(); - handler_->Post(common::BindOnce([](std::promise<void> promise) { promise.set_value(); }, - std::move(promise))); - future.wait_for(std::chrono::milliseconds(kSyncMainLoopTimeoutMs)); - } - - // Stops the client and associated resources - void Stop() { - if (!quiesced_) { - Quiesce(); - } - handler_->Clear(); - handler_->WaitUntilStopped(std::chrono::milliseconds(kWaitUntilHandlerStoppedMs)); - delete handler_; - delete thread_; - } - - int Id() const { return id_; } - - CallablePostCnt GetCallablePostCnt() const { return post_cnt_; } - - std::string Name() const { return common::StringFormat("%s%d", __func__, id_); } - -private: - int id_{0}; - CallablePostCnt post_cnt_{}; - bool quiesced_{false}; - os::Handler* handler_{nullptr}; - os::Thread* thread_{nullptr}; -}; - -// Convenience object to handle multiple clients with logging -class ClientGroup { -public: - ClientGroup() {} - - void Start() { - for (auto& c : clients_) { - c->Start(); - } - log_tag("STARTING"); - } - - void Await() { - for (auto& c : clients_) { - c->Await(); - } - log_tag("STARTED"); - } - - void Quiesce() { - log_tag("QUIESCING"); - for (auto& c : clients_) { - c->Quiesce(); - } - log_tag("QUIESCED"); - } - - void Stop() { - for (auto& c : clients_) { - c->Stop(); - } - log_tag("STOPPED"); - } - - void Dump() const { - for (auto& c : clients_) { - log::info("Callable post cnt client_id:{} success:{} misses:{}", c->Id(), - c->GetCallablePostCnt().success, c->GetCallablePostCnt().misses); - } - } - - CallablePostCnt GetCallablePostCnt() const { - CallablePostCnt post_cnt{}; - for (auto& c : clients_) { - post_cnt += c->GetCallablePostCnt(); - } - return post_cnt; - } - - size_t NumClients() const { return kNumTestClients; } - - std::unique_ptr<Client> clients_[kNumTestClients] = { - std::make_unique<Client>(1), std::make_unique<Client>(2), std::make_unique<Client>(3)}; -}; - -TEST_F(StackLifecycleWithDefaultModulesUnitTest, clients_start) { - ClientGroup client_group; - - client_group.Start(); - client_group.Await(); - - // Clients are operational - - client_group.Quiesce(); - client_group.Stop(); -} - -TEST_F(StackLifecycleWithDefaultModulesUnitTest, client_using_stack_manager) { - ClientGroup client_group; - client_group.Start(); - client_group.Await(); - - for (int i = 0; i < kNumIters; i++) { - for (auto& c : client_group.clients_) { - c->Post(base::BindOnce( - [](int /*id*/, int iter, std::shared_ptr<TestStackManager> stack_manager) { - stack_manager->GetUnsafeModule<TestStackModule1>()->TestMethod({ - .iter = iter, - .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData /*data*/) {}, - }); - }, - c->Id(), i, StackManager())); - c->Post(base::BindOnce( - [](int /*id*/, int iter, std::shared_ptr<TestStackManager> stack_manager) { - stack_manager->GetUnsafeModule<TestStackModule2>()->TestMethod({ - .iter = iter, - .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData /*data*/) {}, - }); - }, - c->Id(), i, StackManager())); - c->Post(base::BindOnce( - [](int /*id*/, int iter, std::shared_ptr<TestStackManager> stack_manager) { - stack_manager->GetUnsafeModule<TestStackModule3>()->TestMethod({ - .iter = iter, - .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData /*data*/) {}, - }); - }, - c->Id(), i, StackManager())); - } - } - - client_group.Quiesce(); - client_group.Stop(); - client_group.Dump(); - - ASSERT_EQ(client_group.NumClients() * kNumIters * kNumTestModules, - client_group.GetCallablePostCnt().success + client_group.GetCallablePostCnt().misses); -} - -TEST_F(StackLifecycleWithDefaultModulesUnitTest, client_using_stack_manager_when_shutdown) { - struct Counters { - struct { - std::atomic_size_t cnt{0}; - } up, down; - } counters; - - ClientGroup client_group; - client_group.Start(); - client_group.Await(); - - for (int i = 0; i < kNumIters; i++) { - for (auto& c : client_group.clients_) { - c->Post(base::BindOnce( - [](int /*id*/, int iter, Counters* counters, - std::shared_ptr<TestStackManager> /*stack_manager*/) { - TestData test_data = { - .iter = iter, - .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData /*data*/) {}, - }; - if (bluetooth::shim::Stack::GetInstance()->CallOnModule<TestStackModule1>( - [test_data](TestStackModule1* mod) { mod->TestMethod(test_data); })) { - counters->up.cnt++; - } else { - counters->down.cnt++; - } - }, - c->Id(), i, &counters, StackManager())); - c->Post(base::BindOnce( - [](int /*id*/, int iter, Counters* counters, - std::shared_ptr<TestStackManager> /*stack_manager*/) { - TestData test_data = { - .iter = iter, - .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData /*data*/) {}, - }; - if (bluetooth::shim::Stack::GetInstance()->CallOnModule<TestStackModule2>( - [test_data](TestStackModule2* mod) { mod->TestMethod(test_data); })) { - counters->up.cnt++; - } else { - counters->down.cnt++; - } - }, - c->Id(), i, &counters, StackManager())); - c->Post(base::BindOnce( - [](int /*id*/, int iter, Counters* counters, - std::shared_ptr<TestStackManager> /*stack_manager*/) { - TestData test_data = { - .iter = iter, - .tag = std::string(kTestDataTag), - .callback = [](TestCallbackData /*data*/) {}, - }; - if (bluetooth::shim::Stack::GetInstance()->CallOnModule<TestStackModule3>( - [test_data](TestStackModule3* mod) { mod->TestMethod(test_data); })) { - counters->up.cnt++; - } else { - counters->down.cnt++; - } - }, - c->Id(), i, &counters, StackManager())); - } - // Abruptly shutdown stack at some point through the iterations - if (i == kAbruptStackShutdownIter) { - log_tag("SHUTTING DOWN STACK"); - StackManager()->Stop(); - } - } - - client_group.Quiesce(); - client_group.Stop(); - log::info("Execution stack availability counters up:{} down:{}", counters.up.cnt, - counters.down.cnt); - - ASSERT_EQ(client_group.NumClients() * kNumIters * kNumTestModules, - client_group.GetCallablePostCnt().success + client_group.GetCallablePostCnt().misses); -} diff --git a/system/stack/Android.bp b/system/stack/Android.bp index 25cf3c5a5d..cb987debfc 100644 --- a/system/stack/Android.bp +++ b/system/stack/Android.bp @@ -813,7 +813,6 @@ cc_test { "libbase", "libbluetooth-dumpsys", "libbluetooth-for-tests", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_core_rs", "libbluetooth_crypto_toolbox", diff --git a/system/stack/test/fuzzers/Android.bp b/system/stack/test/fuzzers/Android.bp index 8d146834d6..3c74de632d 100644 --- a/system/stack/test/fuzzers/Android.bp +++ b/system/stack/test/fuzzers/Android.bp @@ -40,7 +40,6 @@ cc_defaults { "bluetooth_flags_c_lib", "libFraunhoferAAC", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_core_rs", "libbluetooth_crypto_toolbox", diff --git a/system/test/headless/Android.bp b/system/test/headless/Android.bp index 9e0a234742..846f9ec4cc 100644 --- a/system/test/headless/Android.bp +++ b/system/test/headless/Android.bp @@ -82,7 +82,6 @@ cc_binary { "libFraunhoferAAC", "libbase", "libbluetooth-dumpsys", - "libbluetooth-gdx", "libbluetooth-types", "libbluetooth_core_rs", "libbluetooth_crypto_toolbox", diff --git a/system/test/suite/Android.bp b/system/test/suite/Android.bp index 4ce6367d5b..09e8fda413 100644 --- a/system/test/suite/Android.bp +++ b/system/test/suite/Android.bp @@ -121,7 +121,6 @@ cc_test { ], static_libs: [ "bluetooth_flags_c_lib_for_test", - "libbluetooth-gdx", "libbluetooth_crypto_toolbox", "libbluetooth_gd", "libbluetooth_hci_pdl", |