libaudioclient: force onAudioDeviceUpdate on registration

This CL forces the onAudioDeviceUpdate on register event.
It also fixes the loss of callback on AudioTrack or AudioRecord
client if received before ioHandle is assigned.

Test: audio smoke tests
Test: CTS for AudioTrack and AudioRouting

Change-Id: I119b5c407da68a5b55162550bea5fa7e724165d1
Signed-off-by: Francois Gaffie <francois.gaffie@renault.com>
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index b83a441e..33c2008 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -522,8 +522,9 @@
     if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return;
 
     audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE;
-    Vector < wp<AudioDeviceCallback> > callbacks;
-
+    AudioDeviceCallbacks callbacks;
+    bool deviceValidOrChanged = false;
+    Mutex::Autolock _l(mCallbacksLock);
     {
         Mutex::Autolock _l(mLock);
 
@@ -546,6 +547,13 @@
                     ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(ioDesc->mIoHandle);
                     if (ioIndex >= 0) {
                         callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
+                        deviceValidOrChanged = true;
+                    }
+                }
+                if (event == AUDIO_OUTPUT_REGISTERED || event == AUDIO_INPUT_REGISTERED) {
+                    ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(ioDesc->mIoHandle);
+                    if ((ioIndex >= 0) && !mAudioDeviceCallbacks.valueAt(ioIndex).notifiedOnce()) {
+                        callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
                     }
                 }
             }
@@ -584,6 +592,7 @@
             mIoDescriptors.replaceValueFor(ioDesc->mIoHandle, ioDesc);
 
             if (deviceId != ioDesc->getDeviceId()) {
+                deviceValidOrChanged = true;
                 deviceId = ioDesc->getDeviceId();
                 ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(ioDesc->mIoHandle);
                 if (ioIndex >= 0) {
@@ -600,22 +609,28 @@
         } break;
         }
     }
-    bool callbackRemoved = false;
     // callbacks.size() != 0 =>  ioDesc->mIoHandle and deviceId are valid
-    for (size_t i = 0; i < callbacks.size(); ) {
-        sp<AudioDeviceCallback> callback = callbacks[i].promote();
-        if (callback.get() != nullptr) {
-            callback->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId);
-            i++;
-        } else {
-            callbacks.removeAt(i);
-            callbackRemoved = true;
+    if (callbacks.size() != 0) {
+        for (size_t i = 0; i < callbacks.size(); ) {
+            sp<AudioDeviceCallback> callback = callbacks[i].promote();
+            if (callback.get() != nullptr) {
+                // Call the callback only if the device actually changed, the input or output was
+                // opened or closed or the client was newly registered and the callback was never
+                // called
+                if (!callback->notifiedOnce() || deviceValidOrChanged) {
+                    // Must be called without mLock held. May lead to dead lock if calling for
+                    // example getRoutedDevice that updates the device and tries to acquire mLock.
+                    callback->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId);
+                    callback->setNotifiedOnce();
+                }
+                i++;
+            } else {
+                callbacks.removeAt(i);
+            }
         }
-    }
-    // clean up callback list while we are here if some clients have disappeared without
-    // unregistering their callback
-    if (callbackRemoved) {
-        Mutex::Autolock _l(mLock);
+        callbacks.setNotifiedOnce();
+        // clean up callback list while we are here if some clients have disappeared without
+        // unregistering their callback, or if cb was served for the first time since registered
         mAudioDeviceCallbacks.replaceValueFor(ioDesc->mIoHandle, callbacks);
     }
 }
@@ -671,8 +686,8 @@
 status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback(
         const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
 {
-    Mutex::Autolock _l(mLock);
-    Vector < wp<AudioDeviceCallback> > callbacks;
+    Mutex::Autolock _l(mCallbacksLock);
+    AudioDeviceCallbacks callbacks;
     ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo);
     if (ioIndex >= 0) {
         callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
@@ -684,7 +699,7 @@
         }
     }
     callbacks.add(callback);
-
+    callbacks.resetNotifiedOnce();
     mAudioDeviceCallbacks.replaceValueFor(audioIo, callbacks);
     return NO_ERROR;
 }
@@ -692,12 +707,12 @@
 status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback(
         const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo)
 {
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mCallbacksLock);
     ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo);
     if (ioIndex < 0) {
         return INVALID_OPERATION;
     }
-    Vector < wp<AudioDeviceCallback> > callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
+    AudioDeviceCallbacks callbacks = mAudioDeviceCallbacks.valueAt(ioIndex);
 
     size_t cbIndex;
     for (cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) {