psh_utils: Update ServiceSingleton code

The new code handles service death.

Flag: EXEMPT Bugfix
Test: atest service_singleton_tests
Test: power stats show when enabled, after stats service killed
Test: atest powerstats_collector_tests
Test: atest audio_powerstats_benchmark
Test: atest audio_token_benchmark
Test: atest audio_powerstatscollector_benchmark
Bug: 350114693
Change-Id: I0783b3c58ed8412b363b613127873f01ef8d6737
diff --git a/media/utils/ServiceSingleton.cpp b/media/utils/ServiceSingleton.cpp
new file mode 100644
index 0000000..ade7a3e
--- /dev/null
+++ b/media/utils/ServiceSingleton.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ServiceSingleton"
+
+#include <mediautils/ServiceSingleton.h>
+
+namespace android::mediautils {
+
+namespace details {
+
+// To prevent multiple instances in different linkages,
+// we anchor the singleton in a .cpp instead of inlining in the header.
+
+template<typename T>
+requires (std::is_same_v<T, const char*> || std::is_same_v<T, String16>)
+std::shared_ptr<ServiceHandler> ServiceHandler::getInstance(const T& name) {
+    using Key = std::conditional_t<std::is_same_v<T, String16>, String16, std::string>;
+    [[clang::no_destroy]] static constinit std::mutex mutex;
+    [[clang::no_destroy]] static constinit std::shared_ptr<
+            std::map<Key, std::shared_ptr<ServiceHandler>>> map GUARDED_BY(mutex);
+    static constinit bool init GUARDED_BY(mutex) = false;
+
+    std::lock_guard l(mutex);
+    if (!init) {
+        map = std::make_shared<std::map<Key, std::shared_ptr<ServiceHandler>>>();
+        init = true;
+    }
+
+    auto& handler = (*map)[name];
+    if (!handler) {
+        handler = std::make_shared<ServiceHandler>();
+        if constexpr (std::is_same_v<T, String16>) {
+            handler->init_cpp();
+        } else /* constexpr */ {
+            handler->init_ndk();
+        }
+    }
+    return handler;
+}
+
+// Explicit template function instantiation.
+template
+std::shared_ptr<ServiceHandler> ServiceHandler::getInstance<const char*>(const char* const& name);
+
+template
+std::shared_ptr<ServiceHandler> ServiceHandler::getInstance<String16>(const String16& name);
+
+} // details
+
+} // namespace android::mediautils
+