Merge "Revert "Restore "Add "Unlocked device required" parameter to keys"""
diff --git a/modules/audio_remote_submix/audio_hw.cpp b/modules/audio_remote_submix/audio_hw.cpp
index eb6ae92..8c0c097 100644
--- a/modules/audio_remote_submix/audio_hw.cpp
+++ b/modules/audio_remote_submix/audio_hw.cpp
@@ -52,9 +52,9 @@
 
 namespace android {
 
-// Set to 1 to enable extremely verbose logging in this module.
-#define SUBMIX_VERBOSE_LOGGING 0
-#if SUBMIX_VERBOSE_LOGGING
+// Uncomment to enable extremely verbose logging in this module.
+// #define SUBMIX_VERBOSE_LOGGING
+#if defined(SUBMIX_VERBOSE_LOGGING)
 #define SUBMIX_ALOGV(...) ALOGV(__VA_ARGS__)
 #define SUBMIX_ALOGE(...) ALOGE(__VA_ARGS__)
 #else
@@ -205,7 +205,7 @@
     int log_fd;
 #endif // LOG_STREAMS_TO_FILES
 
-    volatile int16_t read_error_count;
+    volatile uint16_t read_error_count;
 };
 
 // Determine whether the specified sample rate is supported by the submix module.
@@ -467,11 +467,9 @@
             rsxadev->routes[route_idx].address);
     if (rsxadev->routes[route_idx].rsxSink != 0) {
         rsxadev->routes[route_idx].rsxSink.clear();
-        rsxadev->routes[route_idx].rsxSink = 0;
     }
     if (rsxadev->routes[route_idx].rsxSource != 0) {
         rsxadev->routes[route_idx].rsxSource.clear();
-        rsxadev->routes[route_idx].rsxSource = 0;
     }
     memset(rsxadev->routes[route_idx].address, 0, AUDIO_DEVICE_MAX_ADDRESS_LEN);
 #ifdef ENABLE_RESAMPLING
@@ -816,8 +814,8 @@
             static uint8_t flush_buffer[64];
             const size_t flushBufferSizeFrames = sizeof(flush_buffer) / frame_size;
             size_t frames_to_flush_from_source = frames - availableToWrite;
-            SUBMIX_ALOGV("out_write(): flushing %d frames from the pipe to avoid blocking",
-                         frames_to_flush_from_source);
+            SUBMIX_ALOGV("out_write(): flushing %llu frames from the pipe to avoid blocking",
+                    (unsigned long long)frames_to_flush_from_source);
             while (frames_to_flush_from_source) {
                 const size_t flush_size = min(frames_to_flush_from_source, flushBufferSizeFrames);
                 frames_to_flush_from_source -= flush_size;
@@ -898,7 +896,8 @@
     }
 
     SUBMIX_ALOGV("out_get_presentation_position() got frames=%llu timestamp sec=%llu",
-            frames ? *frames : -1, timestamp ? timestamp->tv_sec : -1);
+            frames ? (unsigned long long)*frames : -1ULL,
+            timestamp ? (unsigned long long)timestamp->tv_sec : -1ULL);
 
     return ret;
 }
@@ -1541,7 +1540,7 @@
                 audio_bytes_per_sample(config->format);
         const size_t buffer_size = max_buffer_period_size_frames * frame_size_in_bytes;
         SUBMIX_ALOGV("adev_get_input_buffer_size() returns %zu bytes, %zu frames",
-                 buffer_size, buffer_period_size_frames);
+                 buffer_size, max_buffer_period_size_frames);
         return buffer_size;
     }
     return 0;
@@ -1692,10 +1691,10 @@
                     reinterpret_cast<const uint8_t *>(device) -
                             offsetof(struct submix_audio_device, device));
     char msg[100];
-    int n = sprintf(msg, "\nReroute submix audio module:\n");
+    int n = snprintf(msg, sizeof(msg), "\nReroute submix audio module:\n");
     write(fd, &msg, n);
     for (int i=0 ; i < MAX_ROUTES ; i++) {
-        n = sprintf(msg, " route[%d] rate in=%d out=%d, addr=[%s]\n", i,
+        n = snprintf(msg, sizeof(msg), " route[%d] rate in=%d out=%d, addr=[%s]\n", i,
                 rsxadev->routes[i].config.input_sample_rate,
                 rsxadev->routes[i].config.output_sample_rate,
                 rsxadev->routes[i].address);
diff --git a/modules/audio_remote_submix/tests/Android.bp b/modules/audio_remote_submix/tests/Android.bp
new file mode 100644
index 0000000..8e4d42d
--- /dev/null
+++ b/modules/audio_remote_submix/tests/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2018 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.
+
+cc_test {
+    name: "r_submix_tests",
+
+    srcs: ["remote_submix_tests.cpp"],
+
+    shared_libs: [
+        "libhardware",
+        "liblog",
+        "libutils",
+    ],
+
+    cflags: ["-Wall", "-Werror", "-O0", "-g",],
+
+    header_libs: ["libaudiohal_headers"],
+}
diff --git a/modules/audio_remote_submix/tests/remote_submix_tests.cpp b/modules/audio_remote_submix/tests/remote_submix_tests.cpp
new file mode 100644
index 0000000..e644fd4
--- /dev/null
+++ b/modules/audio_remote_submix/tests/remote_submix_tests.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+// To run this test (as root):
+// 1) Build it
+// 2) adb push to /vendor/bin
+// 3) adb shell /vendor/bin/r_submix_tests
+
+#define LOG_TAG "RemoteSubmixTest"
+
+#include <memory>
+
+#include <gtest/gtest.h>
+#include <hardware/audio.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+using namespace android;
+
+static status_t load_audio_interface(const char *if_name, audio_hw_device_t **dev)
+{
+    const hw_module_t *mod;
+    int rc;
+
+    rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
+    if (rc) {
+        ALOGE("%s couldn't load audio hw module %s.%s (%s)", __func__,
+                AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
+        goto out;
+    }
+    rc = audio_hw_device_open(mod, dev);
+    if (rc) {
+        ALOGE("%s couldn't open audio hw device in %s.%s (%s)", __func__,
+                AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
+        goto out;
+    }
+    if ((*dev)->common.version < AUDIO_DEVICE_API_VERSION_MIN) {
+        ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
+        rc = BAD_VALUE;
+        audio_hw_device_close(*dev);
+        goto out;
+    }
+    return OK;
+
+out:
+    *dev = NULL;
+    return rc;
+}
+
+class RemoteSubmixTest : public testing::Test {
+  protected:
+    void SetUp() override;
+    void TearDown() override;
+
+    void OpenInputStream(const char *address, audio_stream_in_t** streamIn);
+    void OpenOutputStream(const char *address, audio_stream_out_t** streamOut);
+    void WriteIntoStream(audio_stream_out_t* streamOut, size_t bufferSize, size_t repeats);
+
+    audio_hw_device_t* mDev;
+};
+
+void RemoteSubmixTest::SetUp() {
+    mDev = nullptr;
+    ASSERT_EQ(OK, load_audio_interface(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, &mDev));
+    ASSERT_NE(nullptr, mDev);
+}
+
+void RemoteSubmixTest::TearDown() {
+    if (mDev != nullptr) {
+        int status = audio_hw_device_close(mDev);
+        mDev = nullptr;
+        ALOGE_IF(status, "Error closing audio hw device %p: %s", mDev, strerror(-status));
+        ASSERT_EQ(0, status);
+    }
+}
+
+void RemoteSubmixTest::OpenInputStream(const char *address, audio_stream_in_t** streamIn) {
+    *streamIn = nullptr;
+    struct audio_config configIn = {};
+    configIn.channel_mask = AUDIO_CHANNEL_IN_MONO;
+    configIn.sample_rate = 48000;
+    status_t result = mDev->open_input_stream(mDev,
+            AUDIO_IO_HANDLE_NONE, AUDIO_DEVICE_NONE, &configIn,
+            streamIn, AUDIO_INPUT_FLAG_NONE, address, AUDIO_SOURCE_DEFAULT);
+    ASSERT_EQ(OK, result);
+    ASSERT_NE(nullptr, *streamIn);
+}
+
+void RemoteSubmixTest::OpenOutputStream(const char *address, audio_stream_out_t** streamOut) {
+    *streamOut = nullptr;
+    struct audio_config configOut = {};
+    configOut.channel_mask = AUDIO_CHANNEL_OUT_MONO;
+    configOut.sample_rate = 48000;
+    status_t result = mDev->open_output_stream(mDev,
+            AUDIO_IO_HANDLE_NONE, AUDIO_DEVICE_NONE, AUDIO_OUTPUT_FLAG_NONE,
+            &configOut, streamOut, address);
+    ASSERT_EQ(OK, result);
+    ASSERT_NE(nullptr, *streamOut);
+}
+
+void RemoteSubmixTest::WriteIntoStream(
+        audio_stream_out_t* streamOut, size_t bufferSize, size_t repeats) {
+    std::unique_ptr<char[]> buffer(new char[bufferSize]);
+    for (size_t i = 0; i < repeats; ++i) {
+        ssize_t result = streamOut->write(streamOut, buffer.get(), bufferSize);
+        EXPECT_EQ(bufferSize, static_cast<size_t>(result));
+    }
+}
+
+TEST_F(RemoteSubmixTest, InitSuccess) {
+    // SetUp must finish with no assertions.
+}
+
+// Verifies that when no input was opened, writing into an output stream does not block.
+TEST_F(RemoteSubmixTest, OutputDoesNotBlockWhenNoInput) {
+    const char *address = "1";
+    audio_stream_out_t* streamOut;
+    OpenOutputStream(address, &streamOut);
+    WriteIntoStream(streamOut, 1024, 16);
+    mDev->close_output_stream(mDev, streamOut);
+}
+
+// Verifies that when input is opened but not reading, writing into an output stream does not block.
+// !!! Currently does not finish because requires setting a parameter from another thread !!!
+TEST_F(RemoteSubmixTest, OutputDoesNotBlockWhenInputStuck) {
+    const char *address = "1";
+    audio_stream_out_t* streamOut;
+    OpenOutputStream(address, &streamOut);
+    audio_stream_in_t* streamIn;
+    OpenInputStream(address, &streamIn);
+    WriteIntoStream(streamOut, 1024, 16);
+    mDev->close_input_stream(mDev, streamIn);
+    mDev->close_output_stream(mDev, streamOut);
+}
diff --git a/modules/gralloc/framebuffer.cpp b/modules/gralloc/framebuffer.cpp
index 9796457..c171711 100644
--- a/modules/gralloc/framebuffer.cpp
+++ b/modules/gralloc/framebuffer.cpp
@@ -332,6 +332,8 @@
             const_cast<int&>(dev->device.minSwapInterval) = 1;
             const_cast<int&>(dev->device.maxSwapInterval) = 1;
             *device = &dev->device.common;
+        } else {
+            free(dev);
         }
     }
     return status;