unique_malloced_ptr: RAII guard for C-style allocations

This type is helpful in cases where we need unique ownership for
memory allocated using the C mechanisms (malloc, etc).

Test: atest libmediautils_test
Change-Id: Ia8b273bfd91c26ed99e6ca1a4087ef77bbc92fc6
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 263ee67..8ba0f72 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -20,6 +20,7 @@
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <hwbinder/IPCThreadState.h>
 #include <media/AudioParameter.h>
+#include <mediautils/memory.h>
 #include <mediautils/SchedulingPolicyService.h>
 #include <utils/Log.h>
 
@@ -275,15 +276,15 @@
                                                std::optional<audio_source_t> source,
                                                audio_devices_t type) {
     LOG_ALWAYS_FATAL_IF(port.type != AUDIO_PORT_TYPE_DEVICE, "port type must be device");
-    char* address;
+    unique_malloced_ptr<char> address;
     if (strcmp(port.ext.device.address, "") != 0) {
         // FIXME: we only support address on first sink with HAL version < 3.0
-        address = audio_device_address_to_parameter(port.ext.device.type, port.ext.device.address);
+        address.reset(
+                audio_device_address_to_parameter(port.ext.device.type, port.ext.device.address));
     } else {
-        address = (char*)calloc(1, 1);
+        address.reset((char*)calloc(1, 1));
     }
-    AudioParameter param = AudioParameter(String8(address));
-    free(address);
+    AudioParameter param = AudioParameter(String8(address.get()));
     param.addInt(String8(AudioParameter::keyRouting), (int)type);
     if (source.has_value()) {
         param.addInt(String8(AudioParameter::keyInputSource), (int)source.value());
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index c1c7df5..ba8f199 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -122,7 +122,10 @@
 
 cc_test {
     name: "libmediautils_test",
-    srcs: ["TimerThread-test.cpp"],
+    srcs: [
+        "memory-test.cpp",
+        "TimerThread-test.cpp",
+    ],
     shared_libs: [
       "libmediautils",
       "libutils",
diff --git a/media/utils/include/mediautils/memory.h b/media/utils/include/mediautils/memory.h
new file mode 100644
index 0000000..cc00bb6
--- /dev/null
+++ b/media/utils/include/mediautils/memory.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 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
+
+namespace android {
+
+namespace {
+struct FreeDeleter {
+    void operator()(void* p) { free(p); }
+};
+
+}  // namespace
+
+/**
+ * Used to wrap pointers allocated by legacy code using malloc / calloc / etc.
+ */
+template <typename T>
+using unique_malloced_ptr = std::unique_ptr<T, FreeDeleter>;
+
+}  // namespace android
diff --git a/media/utils/memory-test.cpp b/media/utils/memory-test.cpp
new file mode 100644
index 0000000..2409bc2
--- /dev/null
+++ b/media/utils/memory-test.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 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 <gtest/gtest.h>
+#include <mediautils/memory.h>
+
+namespace android {
+namespace {
+
+TEST(UniqueMallocedPtr, Void) {
+    unique_malloced_ptr<void> p(std::malloc(10));
+}
+
+TEST(UniqueMallocedPtr, Char) {
+    unique_malloced_ptr<char> p(reinterpret_cast<char*>(std::malloc(10)));
+}
+
+TEST(UniqueMallocedPtr, Null) {
+    unique_malloced_ptr<char> p(nullptr);
+}
+
+TEST(UniqueMallocedPtr, Default) {
+    unique_malloced_ptr<char> p;
+}
+
+}  // namespace
+}  // namespace android