Add a mechanism for handling audio device configuration change

* Added new call handleDeviceConfigChange() to the Media Framework.
  That call can be used when there are device configuration changes
  (e.g., Bluetooth A2DP codec configuration has changed).
* Added new method AudioPolicyManager::handleDeviceConfigChange().
  That method toggles the UNAVAILABLE/AVAILABLE connection state of the
  device, so it can be reconfigured as appropriate - e.g., the audio
  feeding parameters can be updated.
* Fix ALOGVV compilation errors when extra logging is enabled.

Test: A2DP streaming to headsets
Bug: 30958229
Change-Id: I388abbbb3ec4d1a003b441cb0c77e00d80cad668
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 2174b2f..d67ad44 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -200,6 +200,9 @@
                                              const char *device_address, const char *device_name);
     static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
                                                                 const char *device_address);
+    static status_t handleDeviceConfigChange(audio_devices_t device,
+                                             const char *device_address,
+                                             const char *device_name);
     static status_t setPhoneState(audio_mode_t state);
     static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
     static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index ef15a0c..f9dcbea 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -48,6 +48,9 @@
                                               const char *device_name) = 0;
     virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
                                                                   const char *device_address) = 0;
+    virtual status_t handleDeviceConfigChange(audio_devices_t device,
+                                              const char *device_address,
+                                              const char *device_name) = 0;
     virtual status_t setPhoneState(audio_mode_t state) = 0;
     virtual status_t setForceUse(audio_policy_force_use_t usage,
                                     audio_policy_forced_cfg_t config) = 0;
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 33974e0..bbe6a8f 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -751,6 +751,25 @@
     return aps->getDeviceConnectionState(device, device_address);
 }
 
+status_t AudioSystem::handleDeviceConfigChange(audio_devices_t device,
+                                               const char *device_address,
+                                               const char *device_name)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    const char *address = "";
+    const char *name = "";
+
+    if (aps == 0) return PERMISSION_DENIED;
+
+    if (device_address != NULL) {
+        address = device_address;
+    }
+    if (device_name != NULL) {
+        name = device_name;
+    }
+    return aps->handleDeviceConfigChange(device, address, name);
+}
+
 status_t AudioSystem::setPhoneState(audio_mode_t state)
 {
     if (uint32_t(state) >= AUDIO_MODE_CNT) return BAD_VALUE;
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 946da8a..222189a 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -33,6 +33,7 @@
 enum {
     SET_DEVICE_CONNECTION_STATE = IBinder::FIRST_CALL_TRANSACTION,
     GET_DEVICE_CONNECTION_STATE,
+    HANDLE_DEVICE_CONFIG_CHANGE,
     SET_PHONE_STATE,
     SET_RINGER_MODE,    // reserved, no longer used
     SET_FORCE_USE,
@@ -116,6 +117,19 @@
         return static_cast <audio_policy_dev_state_t>(reply.readInt32());
     }
 
+    virtual status_t handleDeviceConfigChange(audio_devices_t device,
+                                              const char *device_address,
+                                              const char *device_name)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(device));
+        data.writeCString(device_address);
+        data.writeCString(device_name);
+        remote()->transact(HANDLE_DEVICE_CONFIG_CHANGE, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
     virtual status_t setPhoneState(audio_mode_t state)
     {
         Parcel data, reply;
@@ -838,6 +852,18 @@
             return NO_ERROR;
         } break;
 
+        case HANDLE_DEVICE_CONFIG_CHANGE: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_devices_t device =
+                    static_cast <audio_devices_t>(data.readInt32());
+            const char *device_address = data.readCString();
+            const char *device_name = data.readCString();
+            reply->writeInt32(static_cast<uint32_t> (handleDeviceConfigChange(device,
+                                                                              device_address,
+                                                                              device_name)));
+            return NO_ERROR;
+        } break;
+
         case SET_PHONE_STATE: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             reply->writeInt32(static_cast <uint32_t>(setPhoneState(
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index bb8a8fa..d1b86da 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -81,6 +81,10 @@
     // retrieve a device connection status
     virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
                                                                           const char *device_address) = 0;
+    // indicate a change in device configuration
+    virtual status_t handleDeviceConfigChange(audio_devices_t device,
+                                              const char *device_address,
+                                              const char *device_name) = 0;
     // indicate a change in phone state. Valid phones states are defined by audio_mode_t
     virtual void setPhoneState(audio_mode_t state) = 0;
     // force using a specific device category for the specified usage
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a8bdf86..8744de8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -333,6 +333,47 @@
             AUDIO_POLICY_DEVICE_STATE_AVAILABLE : AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
 }
 
+status_t AudioPolicyManager::handleDeviceConfigChange(audio_devices_t device,
+                                                      const char *device_address,
+                                                      const char *device_name)
+{
+    status_t status;
+
+    ALOGV("handleDeviceConfigChange(() device: 0x%X, address %s name %s",
+          device, device_address, device_name);
+
+    // Check if the device is currently connected
+    sp<DeviceDescriptor> devDesc =
+            mHwModules.getDeviceDescriptor(device, device_address, device_name);
+    ssize_t index = mAvailableOutputDevices.indexOf(devDesc);
+    if (index < 0) {
+        // Nothing to do: device is not connected
+        return NO_ERROR;
+    }
+
+    // Toggle the device state: UNAVAILABLE -> AVAILABLE
+    // This will force reading again the device configuration
+    status = setDeviceConnectionState(device,
+                                      AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+                                      device_address, device_name);
+    if (status != NO_ERROR) {
+        ALOGW("handleDeviceConfigChange() error disabling connection state: %d",
+              status);
+        return status;
+    }
+
+    status = setDeviceConnectionState(device,
+                                      AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+                                      device_address, device_name);
+    if (status != NO_ERROR) {
+        ALOGW("handleDeviceConfigChange() error enabling connection state: %d",
+              status);
+        return status;
+    }
+
+    return NO_ERROR;
+}
+
 uint32_t AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, uint32_t delayMs)
 {
     bool createTxPatch = false;
@@ -4173,7 +4214,7 @@
 
     ALOGVV("getOutputsForDevice() device %04x", device);
     for (size_t i = 0; i < openOutputs.size(); i++) {
-        ALOGVV("output %d isDuplicated=%d device=%04x",
+        ALOGVV("output %zu isDuplicated=%d device=%04x",
                 i, openOutputs.valueAt(i)->isDuplicated(),
                 openOutputs.valueAt(i)->supportedDevices());
         if ((device & openOutputs.valueAt(i)->supportedDevices()) == device) {
@@ -4614,7 +4655,7 @@
                         == AUDIO_DEVICE_NONE) {
                     continue;
                 }
-                ALOGVV("checkDeviceMuteStrategies() %s strategy %d (curDevice %04x)",
+                ALOGVV("checkDeviceMuteStrategies() %s strategy %zu (curDevice %04x)",
                       mute ? "muting" : "unmuting", i, curDevice);
                 setStrategyMute((routing_strategy)i, mute, desc, mute ? 0 : delayMs);
                 if (isStrategyActive(desc, (routing_strategy)i)) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 5c2b673..3cfe508 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -93,6 +93,9 @@
                                                           const char *device_name);
         virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
                                                                               const char *device_address);
+        virtual status_t handleDeviceConfigChange(audio_devices_t device,
+                                                  const char *device_address,
+                                                  const char *device_name);
         virtual void setPhoneState(audio_mode_t state);
         virtual void setForceUse(audio_policy_force_use_t usage,
                                  audio_policy_forced_cfg_t config);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 451ce84..b4470c0 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -62,6 +62,26 @@
                                                       device_address);
 }
 
+status_t AudioPolicyService::handleDeviceConfigChange(audio_devices_t device,
+                                                  const char *device_address,
+                                                  const char *device_name)
+{
+    if (mAudioPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+    if (!audio_is_output_device(device) && !audio_is_input_device(device)) {
+        return BAD_VALUE;
+    }
+
+    ALOGV("handleDeviceConfigChange()");
+    Mutex::Autolock _l(mLock);
+    return mAudioPolicyManager->handleDeviceConfigChange(device, device_address,
+                                                         device_name);
+}
+
 status_t AudioPolicyService::setPhoneState(audio_mode_t state)
 {
     if (mAudioPolicyManager == NULL) {
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index def6405..8c9b23c 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -66,6 +66,9 @@
     virtual audio_policy_dev_state_t getDeviceConnectionState(
                                                                 audio_devices_t device,
                                                                 const char *device_address);
+    virtual status_t handleDeviceConfigChange(audio_devices_t device,
+                                              const char *device_address,
+                                              const char *device_name);
     virtual status_t setPhoneState(audio_mode_t state);
     virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
     virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);