APM: Notify the client about new audio ports

Added missing notification to the APM client
about new audio ports. This should make the
ports provided by the newly discovered HAL
to be available to apps.

Process the onNewAudioModulesAvailable notification
on the "APM Output" command thread to avoid clashing
with outgoing commands from APM during module
initialization.

Bug: 149854039
Test: atest audiopolicy_tests
Change-Id: I3fede7f5a04419b15e15476d8b5ac7dc6d63c98d
Merged-In: I3fede7f5a04419b15e15476d8b5ac7dc6d63c98d
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 8de8ecd..d1909ea 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -134,12 +134,14 @@
     sp<DeviceDescriptor> device =
             mHwModules.getDeviceDescriptor(deviceType, device_address, device_name, encodedFormat,
                                            state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
-    if (device == 0) {
-        return INVALID_OPERATION;
-    }
+    return device ? setDeviceConnectionStateInt(device, state) : INVALID_OPERATION;
+}
 
+status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescriptor> &device,
+                                                         audio_policy_dev_state_t state)
+{
     // handle output devices
-    if (audio_is_output_device(deviceType)) {
+    if (audio_is_output_device(device->type())) {
         SortedVector <audio_io_handle_t> outputs;
 
         ssize_t index = mAvailableOutputDevices.indexOf(device);
@@ -156,7 +158,7 @@
                 return INVALID_OPERATION;
             }
             ALOGV("%s() connecting device %s format %x",
-                    __func__, device->toString().c_str(), encodedFormat);
+                    __func__, device->toString().c_str(), device->getEncodedFormat());
 
             // register new device as available
             if (mAvailableOutputDevices.add(device) < 0) {
@@ -218,16 +220,13 @@
         // output device used by a dynamic policy of type recorder as no
         // playback use case is affected.
         bool doCheckForDeviceAndOutputChanges = true;
-        if (device->type() == AUDIO_DEVICE_OUT_REMOTE_SUBMIX
-                && strncmp(device_address, "0", AUDIO_DEVICE_MAX_ADDRESS_LEN) != 0) {
+        if (device->type() == AUDIO_DEVICE_OUT_REMOTE_SUBMIX && device->address() != "0") {
             for (audio_io_handle_t output : outputs) {
                 sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
                 sp<AudioPolicyMix> policyMix = desc->mPolicyMix.promote();
                 if (policyMix != nullptr
                         && policyMix->mMixType == MIX_TYPE_RECORDERS
-                        && strncmp(device_address,
-                                   policyMix->mDeviceAddress.string(),
-                                   AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
+                        && device->address() == policyMix->mDeviceAddress.string()) {
                     doCheckForDeviceAndOutputChanges = false;
                     break;
                 }
@@ -273,7 +272,7 @@
                 // a valid device selection on those outputs.
                 bool force = (msdOutDevices.isEmpty() || msdOutDevices != desc->devices())
                         && !desc->isDuplicated()
-                        && (!device_distinguishes_on_address(deviceType)
+                        && (!device_distinguishes_on_address(device->type())
                                 // always force when disconnecting (a non-duplicated device)
                                 || (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
                 setOutputDevices(desc, newDevices, force, 0);
@@ -289,7 +288,7 @@
     }  // end if is output device
 
     // handle input devices
-    if (audio_is_input_device(deviceType)) {
+    if (audio_is_input_device(device->type())) {
         ssize_t index = mAvailableInputDevices.indexOf(device);
         switch (state)
         {
@@ -4387,7 +4386,7 @@
 
     // after parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices;
     // open all output streams needed to access attached devices
-    onNewAudioModulesAvailable();
+    onNewAudioModulesAvailableInt(nullptr /*newDevices*/);
 
     // make sure default device is reachable
     if (mDefaultOutputDevice == 0 || !mAvailableOutputDevices.contains(mDefaultOutputDevice)) {
@@ -4444,6 +4443,16 @@
 
 void AudioPolicyManager::onNewAudioModulesAvailable()
 {
+    DeviceVector newDevices;
+    onNewAudioModulesAvailableInt(&newDevices);
+    if (!newDevices.empty()) {
+        nextAudioPortGeneration();
+        mpClientInterface->onAudioPortListUpdate();
+    }
+}
+
+void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
+{
     for (const auto& hwModule : mHwModulesAll) {
         if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {
             continue;
@@ -4507,6 +4516,7 @@
                 if (!device->isAttached()) {
                     device->attach(hwModule);
                     mAvailableOutputDevices.add(device);
+                    if (newDevices) newDevices->add(device);
                     setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
                 }
             }
@@ -4562,6 +4572,7 @@
                     device->attach(hwModule);
                     device->importAudioPortAndPickAudioProfile(inProfile, true);
                     mAvailableInputDevices.add(device);
+                    if (newDevices) newDevices->add(device);
                     setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
                 }
             }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 4604676..9eb9a1d 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -776,6 +776,8 @@
 
         std::unordered_map<uid_t, audio_flags_mask_t> mAllowedCapturePolicies;
 private:
+        void onNewAudioModulesAvailableInt(DeviceVector *newDevices);
+
         // Add or remove AC3 DTS encodings based on user preferences.
         void modifySurroundFormats(const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr);
         void modifySurroundChannelMasks(ChannelMaskSet *channelMasksPtr);
@@ -865,6 +867,8 @@
                                              const char *device_address,
                                              const char *device_name,
                                              audio_format_t encodedFormat);
+        status_t setDeviceConnectionStateInt(const sp<DeviceDescriptor> &device,
+                                             audio_policy_dev_state_t state);
 
         void setEngineDeviceConnectionState(const sp<DeviceDescriptor> device,
                                       audio_policy_dev_state_t state);
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 3d9278b..c4139d3 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1833,7 +1833,7 @@
 
 void AudioPolicyService::onNewAudioModulesAvailable()
 {
-    mAudioCommandThread->audioModulesUpdateCommand();
+    mOutputCommandThread->audioModulesUpdateCommand();
 }
 
 
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index af69466..e1721ea 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -94,6 +94,10 @@
         return NO_ERROR;
     }
 
+    void onAudioPortListUpdate() override {
+        ++mAudioPortListUpdateCount;
+    }
+
     // Helper methods for tests
     size_t getActivePatchesCount() const { return mActivePatches.size(); }
 
@@ -111,12 +115,15 @@
         mAllowedModuleNames.swap(names);
     }
 
+    size_t getAudioPortListUpdateCount() const { return mAudioPortListUpdateCount; }
+
 private:
     audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
     audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
     audio_patch_handle_t mNextPatchHandle = AUDIO_PATCH_HANDLE_NONE + 1;
     std::map<audio_patch_handle_t, struct audio_patch> mActivePatches;
     std::set<std::string> mAllowedModuleNames;
+    size_t mAudioPortListUpdateCount = 0;
 };
 
 } // namespace android
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index e8c2d33..3640b6d 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -28,6 +28,7 @@
     using AudioPolicyManager::initialize;
     using AudioPolicyManager::getAvailableOutputDevices;
     using AudioPolicyManager::getAvailableInputDevices;
+    uint32_t getAudioPortGeneration() const { return mAudioPortGeneration; }
 };
 
 }  // namespace android
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index acd61ed..0bbb86b 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -103,7 +103,7 @@
             audio_port_handle_t *portId = nullptr);
     PatchCountCheck snapshotPatchCount() { return PatchCountCheck(mClient.get()); }
 
-    void findDevicePort(audio_port_role_t role, audio_devices_t deviceType,
+    bool findDevicePort(audio_port_role_t role, audio_devices_t deviceType,
             const std::string &address, audio_port &foundPort);
     static audio_port_handle_t getDeviceIdFromPatch(const struct audio_patch* patch);
 
@@ -205,30 +205,32 @@
     ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
 }
 
-void AudioPolicyManagerTest::findDevicePort(audio_port_role_t role,
+bool AudioPolicyManagerTest::findDevicePort(audio_port_role_t role,
         audio_devices_t deviceType, const std::string &address, audio_port &foundPort) {
     uint32_t numPorts = 0;
     uint32_t generation1;
     status_t ret;
 
     ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, nullptr, &generation1);
-    ASSERT_EQ(NO_ERROR, ret);
+    EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
+    if (HasFailure()) return false;
 
     uint32_t generation2;
     struct audio_port ports[numPorts];
     ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, ports, &generation2);
-    ASSERT_EQ(NO_ERROR, ret);
-    ASSERT_EQ(generation1, generation2);
+    EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
+    EXPECT_EQ(generation1, generation2) << "Generations changed during ports retrieval";
+    if (HasFailure()) return false;
 
     for (const auto &port : ports) {
         if (port.role == role && port.ext.device.type == deviceType &&
                 (strncmp(port.ext.device.address, address.c_str(),
                          AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
             foundPort = port;
-            return;
+            return true;
         }
     }
-    GTEST_FAIL();
+    return false;
 }
 
 audio_port_handle_t AudioPolicyManagerTest::getDeviceIdFromPatch(
@@ -688,8 +690,8 @@
     ASSERT_EQ(NO_ERROR, ret);
 
     struct audio_port extractionPort;
-    findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
-            mMixAddress, extractionPort);
+    ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+                    mMixAddress, extractionPort));
 
     audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
     audio_source_t source = AUDIO_SOURCE_REMOTE_SUBMIX;
@@ -701,8 +703,8 @@
     ASSERT_EQ(NO_ERROR, mManager->startInput(mPortId));
     ASSERT_EQ(extractionPort.id, selectedDeviceId);
 
-    findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
-            mMixAddress, mInjectionPort);
+    ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+                    mMixAddress, mInjectionPort));
 }
 
 void AudioPolicyManagerTestDPPlaybackReRouting::TearDown() {
@@ -873,8 +875,8 @@
     ASSERT_EQ(NO_ERROR, ret);
 
     struct audio_port injectionPort;
-    findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
-            mMixAddress, injectionPort);
+    ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+                    mMixAddress, injectionPort));
 
     audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
     audio_usage_t usage = AUDIO_USAGE_VIRTUAL_SOURCE;
@@ -886,8 +888,8 @@
     ASSERT_EQ(NO_ERROR, mManager->startOutput(mPortId));
     ASSERT_EQ(injectionPort.id, getDeviceIdFromPatch(mClient->getLastAddedPatch()));
 
-    findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
-            mMixAddress, mExtractionPort);
+    ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+                    mMixAddress, mExtractionPort));
 }
 
 void AudioPolicyManagerTestDPMixRecordInjection::TearDown() {
@@ -1022,7 +1024,7 @@
     audio_port devicePort;
     const audio_port_role_t role = audio_is_output_device(type)
             ? AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
-    findDevicePort(role, type, address, devicePort);
+    ASSERT_TRUE(findDevicePort(role, type, address, devicePort));
 
     audio_port_handle_t routedPortId = devicePort.id;
     audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
@@ -1093,3 +1095,20 @@
     ASSERT_EQ(AUDIO_POLICY_DEVICE_STATE_AVAILABLE, mManager->getDeviceConnectionState(
                     AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0"));
 }
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, ListAddedAudioPorts) {
+    struct audio_port port;
+    ASSERT_FALSE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port));
+    mClient->swapAllowedModuleNames({"primary", "r_submix"});
+    mManager->onNewAudioModulesAvailable();
+    ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port));
+}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, ClientIsUpdated) {
+    const size_t prevAudioPortListUpdateCount = mClient->getAudioPortListUpdateCount();
+    const uint32_t prevAudioPortGeneration = mManager->getAudioPortGeneration();
+    mClient->swapAllowedModuleNames({"primary", "r_submix"});
+    mManager->onNewAudioModulesAvailable();
+    EXPECT_GT(mClient->getAudioPortListUpdateCount(), prevAudioPortListUpdateCount);
+    EXPECT_GT(mManager->getAudioPortGeneration(), prevAudioPortGeneration);
+}