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/src/binding/AAudioBinderClient.cpp b/media/libaaudio/src/binding/AAudioBinderClient.cpp
index c45bd71..6464334 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.cpp
+++ b/media/libaaudio/src/binding/AAudioBinderClient.cpp
@@ -19,75 +19,101 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <binder/IInterface.h>
#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
#include <utils/Mutex.h>
#include <utils/RefBase.h>
#include <utils/Singleton.h>
+#include <media/AudioSystem.h>
#include <aaudio/AAudio.h>
#include "AudioEndpointParcelable.h"
-#include "binding/AAudioStreamRequest.h"
-#include "binding/AAudioStreamConfiguration.h"
-#include "binding/IAAudioService.h"
-#include "binding/AAudioServiceMessage.h"
+#include "binding/AAudioBinderClient.h"
+//#include "binding/AAudioStreamRequest.h"
+//#include "binding/AAudioStreamConfiguration.h"
+//#include "binding/IAAudioService.h"
+//#include "binding/AAudioServiceMessage.h"
-#include "AAudioBinderClient.h"
-#include "AAudioServiceInterface.h"
+//#include "AAudioServiceInterface.h"
using android::String16;
using android::IServiceManager;
using android::defaultServiceManager;
using android::interface_cast;
+using android::IInterface;
using android::IAAudioService;
using android::Mutex;
using android::sp;
+using android::wp;
using namespace aaudio;
-static android::Mutex gServiceLock;
-static sp<IAAudioService> gAAudioService;
-
ANDROID_SINGLETON_STATIC_INSTANCE(AAudioBinderClient);
+AAudioBinderClient::AAudioBinderClient()
+ : AAudioServiceInterface()
+ , Singleton<AAudioBinderClient>() {
+
+ mAAudioClient = new AAudioClient(this);
+ ALOGD("AAudioBinderClient() created mAAudioClient = %p", mAAudioClient.get());
+}
+
+AAudioBinderClient::~AAudioBinderClient() {
+ Mutex::Autolock _l(mServiceLock);
+ if (mAAudioService != 0) {
+ IInterface::asBinder(mAAudioService)->unlinkToDeath(mAAudioClient);
+ }
+}
+
// TODO Share code with other service clients.
// Helper function to get access to the "AAudioService" service.
// This code was modeled after frameworks/av/media/libaudioclient/AudioSystem.cpp
-static const sp<IAAudioService> getAAudioService() {
- sp<IBinder> binder;
- Mutex::Autolock _l(gServiceLock);
- if (gAAudioService == 0) {
- sp<IServiceManager> sm = defaultServiceManager();
- // Try several times to get the service.
- int retries = 4;
- do {
- binder = sm->getService(String16(AAUDIO_SERVICE_NAME)); // This will wait a while.
+const sp<IAAudioService> AAudioBinderClient::getAAudioService() {
+ sp<IAAudioService> aaudioService;
+ bool needToRegister = false;
+ {
+ Mutex::Autolock _l(mServiceLock);
+ if (mAAudioService == 0) {
+ sp<IBinder> binder;
+ sp<IServiceManager> sm = defaultServiceManager();
+ // Try several times to get the service.
+ int retries = 4;
+ do {
+ binder = sm->getService(String16(AAUDIO_SERVICE_NAME)); // This will wait a while.
+ if (binder != 0) {
+ break;
+ }
+ } while (retries-- > 0);
+
if (binder != 0) {
- break;
+ // Ask for notification if the service dies.
+ status_t status = binder->linkToDeath(mAAudioClient);
+ ALOGD("getAAudioService: linkToDeath(mAAudioClient = %p) returned %d",
+ mAAudioClient.get(), status);
+ mAAudioService = interface_cast<IAAudioService>(binder);
+ needToRegister = true;
+ // Make sure callbacks can be received by mAAudioClient
+ android::ProcessState::self()->startThreadPool();
+ } else {
+ ALOGE("AAudioBinderClient could not connect to %s", AAUDIO_SERVICE_NAME);
}
- } while (retries-- > 0);
-
- if (binder != 0) {
- // TODO Add linkToDeath() like in frameworks/av/media/libaudioclient/AudioSystem.cpp
- // TODO Create a DeathRecipient that disconnects all active streams.
- gAAudioService = interface_cast<IAAudioService>(binder);
- } else {
- ALOGE("AudioStreamInternal could not get %s", AAUDIO_SERVICE_NAME);
}
+ aaudioService = mAAudioService;
}
- return gAAudioService;
+ // Do this outside the mutex lock.
+ if (needToRegister && aaudioService != 0) { // new client?
+ aaudioService->registerClient(mAAudioClient);
+ }
+ return aaudioService;
}
-static void dropAAudioService() {
- Mutex::Autolock _l(gServiceLock);
- gAAudioService.clear(); // force a reconnect
+void AAudioBinderClient::dropAAudioService() {
+ Mutex::Autolock _l(mServiceLock);
+ mAAudioService.clear(); // force a reconnect
}
-AAudioBinderClient::AAudioBinderClient()
- : AAudioServiceInterface()
- , Singleton<AAudioBinderClient>() {}
-
-AAudioBinderClient::~AAudioBinderClient() {}
/**
* @param request info needed to create the stream
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.h b/media/libaaudio/src/binding/AAudioBinderClient.h
index 7cf7bf8..469f0a8 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.h
+++ b/media/libaaudio/src/binding/AAudioBinderClient.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_AAUDIO_AAUDIO_BINDER_CLIENT_H
#define ANDROID_AAUDIO_AAUDIO_BINDER_CLIENT_H
+#include <utils/RefBase.h>
#include <utils/Singleton.h>
#include <aaudio/AAudio.h>
@@ -25,14 +26,16 @@
#include "binding/AAudioStreamRequest.h"
#include "binding/AAudioStreamConfiguration.h"
#include "binding/AudioEndpointParcelable.h"
+#include "binding/IAAudioService.h"
/**
- * Implements the AAudioServiceInterface by talking to the actual service through Binder.
+ * Implements the AAudioServiceInterface by talking to the service through Binder.
*/
namespace aaudio {
-class AAudioBinderClient : public AAudioServiceInterface
+class AAudioBinderClient : public virtual android::RefBase
+ , public AAudioServiceInterface
, public android::Singleton<AAudioBinderClient> {
public:
@@ -41,6 +44,12 @@
virtual ~AAudioBinderClient();
+ const android::sp<android::IAAudioService> getAAudioService();
+
+ void dropAAudioService();
+
+ void registerClient(const android::sp<android::IAAudioClient>& client __unused) override {}
+
/**
* @param request info needed to create the stream
* @param configuration contains resulting information about the created stream
@@ -87,6 +96,45 @@
aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
pid_t clientThreadId) override;
+
+ void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) {
+ // TODO This is just a stub so we can have a client Binder to pass to the service.
+ // TODO Implemented in a later CL.
+ ALOGW("onStreamChange called!");
+ }
+
+ class AAudioClient : public android::IBinder::DeathRecipient , public android::BnAAudioClient
+ {
+ public:
+ AAudioClient(android::wp<AAudioBinderClient> aaudioBinderClient)
+ : mBinderClient(aaudioBinderClient) {
+ }
+
+ // implement DeathRecipient
+ virtual void binderDied(const android::wp<android::IBinder>& who __unused) {
+ android::sp<AAudioBinderClient> client = mBinderClient.promote();
+ if (client != 0) {
+ client->dropAAudioService();
+ }
+ ALOGW("AAudio service binderDied()!");
+ }
+
+ // implement BnAAudioClient
+ void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) {
+ android::sp<AAudioBinderClient> client = mBinderClient.promote();
+ if (client != 0) {
+ client->onStreamChange(handle, opcode, value);
+ }
+ }
+ private:
+ android::wp<AAudioBinderClient> mBinderClient;
+ };
+
+
+ android::Mutex mServiceLock;
+ android::sp<android::IAAudioService> mAAudioService;
+ android::sp<AAudioClient> mAAudioClient;
+
};
diff --git a/media/libaaudio/src/binding/AAudioServiceDefinitions.h b/media/libaaudio/src/binding/AAudioServiceDefinitions.h
index 638544e..8a2303c 100644
--- a/media/libaaudio/src/binding/AAudioServiceDefinitions.h
+++ b/media/libaaudio/src/binding/AAudioServiceDefinitions.h
@@ -29,8 +29,9 @@
namespace android {
-enum aaudio_commands_t {
- OPEN_STREAM = IBinder::FIRST_CALL_TRANSACTION,
+enum aaudio_service_commands_t {
+ REGISTER_CLIENT = IBinder::FIRST_CALL_TRANSACTION,
+ OPEN_STREAM,
CLOSE_STREAM,
GET_STREAM_DESCRIPTION,
START_STREAM,
@@ -41,6 +42,10 @@
UNREGISTER_AUDIO_THREAD
};
+enum aaudio_client_commands_t {
+ ON_STREAM_CHANGE = IBinder::FIRST_CALL_TRANSACTION
+};
+
} // namespace android
namespace aaudio {
diff --git a/media/libaaudio/src/binding/AAudioServiceInterface.h b/media/libaaudio/src/binding/AAudioServiceInterface.h
index d6a130f..7368062 100644
--- a/media/libaaudio/src/binding/AAudioServiceInterface.h
+++ b/media/libaaudio/src/binding/AAudioServiceInterface.h
@@ -17,10 +17,13 @@
#ifndef ANDROID_AAUDIO_BINDING_AAUDIO_SERVICE_INTERFACE_H
#define ANDROID_AAUDIO_BINDING_AAUDIO_SERVICE_INTERFACE_H
+#include <utils/StrongPointer.h>
+
#include "binding/AAudioServiceDefinitions.h"
#include "binding/AAudioStreamRequest.h"
#include "binding/AAudioStreamConfiguration.h"
#include "binding/AudioEndpointParcelable.h"
+#include "binding/IAAudioClient.h"
/**
* This has the same methods as IAAudioService but without the Binder features.
@@ -36,6 +39,8 @@
AAudioServiceInterface() {};
virtual ~AAudioServiceInterface() = default;
+ virtual void registerClient(const android::sp<android::IAAudioClient>& client) = 0;
+
/**
* @param request info needed to create the stream
* @param configuration contains information about the created stream
diff --git a/media/libaaudio/src/binding/AAudioStreamRequest.h b/media/libaaudio/src/binding/AAudioStreamRequest.h
index 77138da..462246b 100644
--- a/media/libaaudio/src/binding/AAudioStreamRequest.h
+++ b/media/libaaudio/src/binding/AAudioStreamRequest.h
@@ -68,7 +68,6 @@
mSharingModeMatchRequired = required;
}
-
const AAudioStreamConfiguration &getConstantConfiguration() const {
return mConfiguration;
}
diff --git a/media/libaaudio/src/binding/IAAudioClient.cpp b/media/libaaudio/src/binding/IAAudioClient.cpp
new file mode 100644
index 0000000..c69c4e8
--- /dev/null
+++ b/media/libaaudio/src/binding/IAAudioClient.cpp
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "AAudio"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <aaudio/AAudio.h>
+
+#include "binding/AAudioBinderClient.h"
+#include "binding/AAudioServiceDefinitions.h"
+#include "binding/IAAudioClient.h"
+#include "utility/AAudioUtilities.h"
+
+namespace android {
+
+using aaudio::aaudio_handle_t;
+
+/**
+ * This is used by the AAudio Service to talk to an AAudio Client.
+ *
+ * The order of parameters in the Parcels must match with code in AAudioClient.cpp.
+ */
+class BpAAudioClient : public BpInterface<IAAudioClient>
+{
+public:
+ explicit BpAAudioClient(const sp<IBinder>& impl)
+ : BpInterface<IAAudioClient>(impl)
+ {
+ }
+
+ void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) override {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAAudioClient::getInterfaceDescriptor());
+ data.writeInt32(handle);
+ data.writeInt32(opcode);
+ data.writeInt32(value);
+ remote()->transact(ON_STREAM_CHANGE, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+
+};
+
+// Implement an interface to the service.
+IMPLEMENT_META_INTERFACE(AAudioClient, "IAAudioClient");
+
+// The order of parameters in the Parcels must match with code in BpAAudioClient
+
+status_t BnAAudioClient::onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags) {
+ aaudio_handle_t streamHandle;
+ int32_t opcode = 0;
+ int32_t value = 0;
+ ALOGV("BnAAudioClient::onTransact(%u) %u", code, flags);
+
+ switch(code) {
+ case ON_STREAM_CHANGE: {
+ CHECK_INTERFACE(IAAudioClient, data, reply);
+ data.readInt32(&streamHandle);
+ data.readInt32(&opcode);
+ data.readInt32(&value);
+ onStreamChange(streamHandle, opcode, value);
+ ALOGD("BnAAudioClient onStreamChange(%x, %d, %d)", streamHandle, opcode, value);
+ return NO_ERROR;
+ } break;
+
+ default:
+ // ALOGW("BnAAudioClient::onTransact not handled %u", code);
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+} /* namespace android */
diff --git a/media/libaaudio/src/binding/IAAudioClient.h b/media/libaaudio/src/binding/IAAudioClient.h
new file mode 100644
index 0000000..21cc33b
--- /dev/null
+++ b/media/libaaudio/src/binding/IAAudioClient.h
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_AAUDIO_IAAUDIO_CLIENT_H
+#define ANDROID_AAUDIO_IAAUDIO_CLIENT_H
+
+#include <stdint.h>
+#include <binder/IInterface.h>
+
+#include <aaudio/AAudio.h>
+
+#include "utility/HandleTracker.h"
+
+namespace android {
+
+
+// Interface (our AIDL) - client methods called by service
+class IAAudioClient : public IInterface {
+public:
+
+ DECLARE_META_INTERFACE(AAudioClient);
+
+ virtual void onStreamChange(aaudio_handle_t handle, int32_t opcode, int32_t value) = 0;
+
+};
+
+class BnAAudioClient : public BnInterface<IAAudioClient> {
+public:
+ virtual status_t onTransact(uint32_t code, const Parcel& data,
+ Parcel* reply, uint32_t flags = 0);
+};
+
+} /* namespace android */
+
+#endif //ANDROID_AAUDIO_IAAUDIO_SERVICE_H
diff --git a/media/libaaudio/src/binding/IAAudioService.cpp b/media/libaaudio/src/binding/IAAudioService.cpp
index e4bf82a..97fbaaa 100644
--- a/media/libaaudio/src/binding/IAAudioService.cpp
+++ b/media/libaaudio/src/binding/IAAudioService.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+#define LOG_TAG "AAudio"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
#include <aaudio/AAudio.h>
#include <binder/IPCThreadState.h>
@@ -41,8 +45,16 @@
{
}
- virtual aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
- aaudio::AAudioStreamConfiguration &configurationOutput) override {
+ void registerClient(const sp<IAAudioClient>& client) override
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
+ data.writeStrongBinder(IInterface::asBinder(client));
+ remote()->transact(REGISTER_CLIENT, data, &reply);
+ }
+
+ aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
+ aaudio::AAudioStreamConfiguration &configurationOutput) override {
Parcel data, reply;
// send command
data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
@@ -56,7 +68,6 @@
// parse reply
aaudio_handle_t stream;
err = reply.readInt32(&stream);
- ALOGD("BpAAudioService::client openStream returned stream = 0x%08x", stream);
if (err != NO_ERROR) {
ALOGE("BpAAudioService::client transact(OPEN_STREAM) readInt %d", err);
return AAudioConvert_androidToAAudioResult(err);
@@ -233,7 +244,7 @@
status_t BnAAudioService::onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags) {
- aaudio_handle_t stream;
+ aaudio_handle_t streamHandle;
aaudio::AAudioStreamRequest request;
aaudio::AAudioStreamConfiguration configuration;
pid_t tid;
@@ -242,6 +253,14 @@
ALOGV("BnAAudioService::onTransact(%i) %i", code, flags);
switch(code) {
+ case REGISTER_CLIENT: {
+ CHECK_INTERFACE(IAAudioService, data, reply);
+ sp<IAAudioClient> client = interface_cast<IAAudioClient>(
+ data.readStrongBinder());
+ registerClient(client);
+ return NO_ERROR;
+ } break;
+
case OPEN_STREAM: {
CHECK_INTERFACE(IAAudioService, data, reply);
request.readFromParcel(&data);
@@ -250,28 +269,28 @@
// Override the uid and pid from the client in case they are incorrect.
request.setUserId(IPCThreadState::self()->getCallingUid());
request.setProcessId(IPCThreadState::self()->getCallingPid());
- stream = openStream(request, configuration);
- //ALOGD("BnAAudioService::onTransact OPEN_STREAM server handle = 0x%08X ----", stream);
- reply->writeInt32(stream);
+ streamHandle = openStream(request, configuration);
+ //ALOGD("BnAAudioService::onTransact OPEN_STREAM server handle = 0x%08X", streamHandle);
+ reply->writeInt32(streamHandle);
configuration.writeToParcel(reply);
return NO_ERROR;
} break;
case CLOSE_STREAM: {
CHECK_INTERFACE(IAAudioService, data, reply);
- data.readInt32(&stream);
- result = closeStream(stream);
+ data.readInt32(&streamHandle);
+ result = closeStream(streamHandle);
//ALOGD("BnAAudioService::onTransact CLOSE_STREAM 0x%08X, result = %d",
- // stream, result);
+ // streamHandle, result);
reply->writeInt32(result);
return NO_ERROR;
} break;
case GET_STREAM_DESCRIPTION: {
CHECK_INTERFACE(IAAudioService, data, reply);
- data.readInt32(&stream);
+ data.readInt32(&streamHandle);
aaudio::AudioEndpointParcelable parcelable;
- result = getStreamDescription(stream, parcelable);
+ result = getStreamDescription(streamHandle, parcelable);
if (result != AAUDIO_OK) {
return AAudioConvert_aaudioToAndroidStatus(result);
}
@@ -288,63 +307,63 @@
case START_STREAM: {
CHECK_INTERFACE(IAAudioService, data, reply);
- data.readInt32(&stream);
- result = startStream(stream);
+ data.readInt32(&streamHandle);
+ result = startStream(streamHandle);
ALOGV("BnAAudioService::onTransact START_STREAM 0x%08X, result = %d",
- stream, result);
+ streamHandle, result);
reply->writeInt32(result);
return NO_ERROR;
} break;
case PAUSE_STREAM: {
CHECK_INTERFACE(IAAudioService, data, reply);
- data.readInt32(&stream);
- result = pauseStream(stream);
+ data.readInt32(&streamHandle);
+ result = pauseStream(streamHandle);
ALOGV("BnAAudioService::onTransact PAUSE_STREAM 0x%08X, result = %d",
- stream, result);
+ streamHandle, result);
reply->writeInt32(result);
return NO_ERROR;
} break;
case STOP_STREAM: {
CHECK_INTERFACE(IAAudioService, data, reply);
- data.readInt32(&stream);
- result = stopStream(stream);
+ data.readInt32(&streamHandle);
+ result = stopStream(streamHandle);
ALOGV("BnAAudioService::onTransact STOP_STREAM 0x%08X, result = %d",
- stream, result);
+ streamHandle, result);
reply->writeInt32(result);
return NO_ERROR;
} break;
case FLUSH_STREAM: {
CHECK_INTERFACE(IAAudioService, data, reply);
- data.readInt32(&stream);
- result = flushStream(stream);
+ data.readInt32(&streamHandle);
+ result = flushStream(streamHandle);
ALOGV("BnAAudioService::onTransact FLUSH_STREAM 0x%08X, result = %d",
- stream, result);
+ streamHandle, result);
reply->writeInt32(result);
return NO_ERROR;
} break;
case REGISTER_AUDIO_THREAD: {
CHECK_INTERFACE(IAAudioService, data, reply);
- data.readInt32(&stream);
+ data.readInt32(&streamHandle);
data.readInt32(&tid);
data.readInt64(&nanoseconds);
- result = registerAudioThread(stream, tid, nanoseconds);
+ result = registerAudioThread(streamHandle, tid, nanoseconds);
ALOGV("BnAAudioService::onTransact REGISTER_AUDIO_THREAD 0x%08X, result = %d",
- stream, result);
+ streamHandle, result);
reply->writeInt32(result);
return NO_ERROR;
} break;
case UNREGISTER_AUDIO_THREAD: {
CHECK_INTERFACE(IAAudioService, data, reply);
- data.readInt32(&stream);
+ data.readInt32(&streamHandle);
data.readInt32(&tid);
- result = unregisterAudioThread(stream, tid);
+ result = unregisterAudioThread(streamHandle, tid);
ALOGV("BnAAudioService::onTransact UNREGISTER_AUDIO_THREAD 0x%08X, result = %d",
- stream, result);
+ streamHandle, result);
reply->writeInt32(result);
return NO_ERROR;
} break;
diff --git a/media/libaaudio/src/binding/IAAudioService.h b/media/libaaudio/src/binding/IAAudioService.h
index 071c5b8..30b3ead 100644
--- a/media/libaaudio/src/binding/IAAudioService.h
+++ b/media/libaaudio/src/binding/IAAudioService.h
@@ -28,18 +28,24 @@
#include "binding/AudioEndpointParcelable.h"
#include "binding/AAudioStreamRequest.h"
#include "binding/AAudioStreamConfiguration.h"
+#include "binding/IAAudioClient.h"
#include "utility/HandleTracker.h"
namespace android {
#define AAUDIO_SERVICE_NAME "media.aaudio"
-// Interface (our AIDL) - Shared by server and client
+// Interface (our AIDL) - service methods called by client
class IAAudioService : public IInterface {
public:
DECLARE_META_INTERFACE(AAudioService);
+ // Register an object to receive audio input/output change and track notifications.
+ // For a given calling pid, AAudio service disregards any registrations after the first.
+ // Thus the IAAudioClient must be a singleton per process.
+ virtual void registerClient(const sp<IAAudioClient>& client) = 0;
+
/**
* @param request info needed to create the stream
* @param configuration contains information about the created stream