aaudio: close MMAP stream if client dies

Notify client when audio service dies. Clear connection.
Notify AAudio service when client dies. Close client streams.

Use sp<> to track ServiceStreams.

Bug: 38267698
Test: test_no_close.cpp
Change-Id: I5f1699ed3b8b7bd960947c0028a89ca8419ce7a0
diff --git a/media/libaaudio/tests/test_recovery.cpp b/media/libaaudio/tests/test_recovery.cpp
new file mode 100644
index 0000000..7268a30
--- /dev/null
+++ b/media/libaaudio/tests/test_recovery.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+// Play silence and recover from dead servers or disconnected devices.
+
+#include <stdio.h>
+
+#include <aaudio/AAudio.h>
+
+
+#define DEFAULT_TIMEOUT_NANOS  ((int64_t)1000000000)
+
+static const char *getSharingModeText(aaudio_sharing_mode_t mode) {
+    const char *modeText = "unknown";
+    switch (mode) {
+        case AAUDIO_SHARING_MODE_EXCLUSIVE:
+            modeText = "EXCLUSIVE";
+            break;
+        case AAUDIO_SHARING_MODE_SHARED:
+            modeText = "SHARED";
+            break;
+        default:
+            break;
+    }
+    return modeText;
+}
+
+int main(int argc, char **argv) {
+    (void) argc;
+    (void *)argv;
+
+    aaudio_result_t result = AAUDIO_OK;
+
+    int32_t triesLeft = 3;
+    int32_t bufferCapacity;
+    int32_t framesPerBurst = 0;
+    float *buffer = nullptr;
+
+    int32_t actualChannelCount = 0;
+    int32_t actualSampleRate = 0;
+    aaudio_format_t actualDataFormat = AAUDIO_FORMAT_PCM_FLOAT;
+    aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_SHARED;
+
+    AAudioStreamBuilder *aaudioBuilder = nullptr;
+    AAudioStream *aaudioStream = nullptr;
+
+    // Make printf print immediately so that debug info is not stuck
+    // in a buffer if we hang or crash.
+    setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
+
+    printf("TestRecovery:\n");
+
+    // Use an AAudioStreamBuilder to contain requested parameters.
+    result = AAudio_createStreamBuilder(&aaudioBuilder);
+    if (result != AAUDIO_OK) {
+        printf("AAudio_createStreamBuilder returned %s",
+               AAudio_convertResultToText(result));
+        goto finish;
+    }
+
+    // Request stream properties.
+    AAudioStreamBuilder_setFormat(aaudioBuilder, AAUDIO_FORMAT_PCM_FLOAT);
+
+    while (triesLeft-- > 0) {
+        // Create an AAudioStream using the Builder.
+        result = AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream);
+        if (result != AAUDIO_OK) {
+            printf("AAudioStreamBuilder_openStream returned %s",
+                   AAudio_convertResultToText(result));
+            goto finish;
+        }
+
+        // Check to see what kind of stream we actually got.
+        actualSampleRate = AAudioStream_getSampleRate(aaudioStream);
+        actualChannelCount = AAudioStream_getChannelCount(aaudioStream);
+        actualDataFormat = AAudioStream_getFormat(aaudioStream);
+
+        printf("-------- chans = %3d, rate = %6d format = %d\n",
+                actualChannelCount, actualSampleRate, actualDataFormat);
+
+        // This is the number of frames that are read in one chunk by a DMA controller
+        // or a DSP or a mixer.
+        framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
+        bufferCapacity = AAudioStream_getBufferCapacityInFrames(aaudioStream);
+        printf("         bufferCapacity = %d, framesPerBurst = %d\n",
+        bufferCapacity, framesPerBurst);
+
+        int samplesPerBurst = framesPerBurst * actualChannelCount;
+        buffer = new float[samplesPerBurst];
+
+        result = AAudioStream_requestStart(aaudioStream);
+        if (result != AAUDIO_OK) {
+            printf("AAudioStream_requestStart returned %s",
+                   AAudio_convertResultToText(result));
+            goto finish;
+        }
+
+        // Play silence for awhile.
+        int32_t framesMax = actualSampleRate * 20;
+        int64_t framesTotal = 0;
+        int64_t printAt = actualSampleRate;
+        while (result == AAUDIO_OK && framesTotal < framesMax) {
+            int32_t framesWritten = AAudioStream_write(aaudioStream,
+                                                       buffer, framesPerBurst,
+                                                       DEFAULT_TIMEOUT_NANOS);
+            if (framesWritten < 0) {
+                result = framesWritten;
+                printf("write() returned %s, frames = %d\n",
+                       AAudio_convertResultToText(result), (int)framesTotal);
+                printf("  frames = %d\n", (int)framesTotal);
+            } else if (framesWritten != framesPerBurst) {
+                printf("write() returned %d, frames = %d\n", framesWritten, (int)framesTotal);
+                result = AAUDIO_ERROR_TIMEOUT;
+            } else {
+                framesTotal += framesWritten;
+                if (framesTotal >= printAt) {
+                    printf("frames = %d\n", (int)framesTotal);
+                    printAt += actualSampleRate;
+                }
+            }
+        }
+        result = AAudioStream_requestStop(aaudioStream);
+        if (result != AAUDIO_OK) {
+            printf("AAudioStream_requestStop returned %s\n",
+                   AAudio_convertResultToText(result));
+        }
+        result = AAudioStream_close(aaudioStream);
+        if (result != AAUDIO_OK) {
+            printf("AAudioStream_close returned %s\n",
+                   AAudio_convertResultToText(result));
+        }
+        aaudioStream = nullptr;
+    }
+
+finish:
+    if (aaudioStream != nullptr) {
+        AAudioStream_close(aaudioStream);
+    }
+    AAudioStreamBuilder_delete(aaudioBuilder);
+    delete[] buffer;
+    printf("          result = %d = %s\n", result, AAudio_convertResultToText(result));
+}