Adding IAudioControl#onDevicesToDuckChange

Introducing new API and parcelable for informing the HAL when to duck
audio for automotive targets.

Bug: 158242859
Test: atest VtsAidlHalAudioControlTest
Change-Id: I5799c556e338d768ea8010e1f035af8584a240dd
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
new file mode 100644
index 0000000..6d729e2
--- /dev/null
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.automotive.audiocontrol;
+@VintfStability
+parcelable DuckingInfo {
+  int zoneId;
+  String[] deviceAddressesToDuck;
+  String[] deviceAddressesToUnduck;
+  String[] usagesHoldingFocus;
+}
diff --git a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl
index 6916846..e5a0451 100644
--- a/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl
+++ b/automotive/audiocontrol/aidl/aidl_api/android.hardware.automotive.audiocontrol/current/android/hardware/automotive/audiocontrol/IAudioControl.aidl
@@ -19,6 +19,7 @@
 @VintfStability
 interface IAudioControl {
   oneway void onAudioFocusChange(in String usage, in int zoneId, in android.hardware.automotive.audiocontrol.AudioFocusChange focusChange);
+  oneway void onDevicesToDuckChange(in android.hardware.automotive.audiocontrol.DuckingInfo[] duckingInfos);
   oneway void registerFocusListener(in android.hardware.automotive.audiocontrol.IFocusListener listener);
   oneway void setBalanceTowardRight(in float value);
   oneway void setFadeTowardFront(in float value);
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
new file mode 100644
index 0000000..e95fe9b
--- /dev/null
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/DuckingInfo.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+ package android.hardware.automotive.audiocontrol;
+
+ /**
+  * The current ducking information for a single audio zone.
+  *
+  * <p>This includes devices to duck, as well as unduck based on the contents of a previous
+  * {@link DuckingInfo}. Additionally, the current usages holding focus in the specified zone are
+  * included, which were used to determine which addresses to duck.
+  */
+ @VintfStability
+ parcelable DuckingInfo {
+     /**
+      * ID of the associated audio zone
+      */
+     int zoneId;
+
+     /**
+      * List of addresses for audio output devices that should be ducked.
+      *
+      * <p>The provided address strings are defined in audio_policy_configuration.xml.
+      */
+     String[] deviceAddressesToDuck;
+
+     /**
+      * List of addresses for audio output devices that were previously be ducked and should now be
+      * unducked.
+      *
+      * <p>The provided address strings are defined in audio_policy_configuration.xml.
+      */
+     String[] deviceAddressesToUnduck;
+
+     /**
+      * List of usages currently holding focus for this audio zone.
+      *
+      * <p> See {@code audioUsage} in audio_policy_configuration.xsd for the list of allowed values.
+      */
+     String[] usagesHoldingFocus;
+ }
\ No newline at end of file
diff --git a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl
index 0641691..4b03af1 100644
--- a/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl
+++ b/automotive/audiocontrol/aidl/android/hardware/automotive/audiocontrol/IAudioControl.aidl
@@ -17,6 +17,7 @@
 package android.hardware.automotive.audiocontrol;
 
 import android.hardware.automotive.audiocontrol.AudioFocusChange;
+import android.hardware.automotive.audiocontrol.DuckingInfo;
 import android.hardware.automotive.audiocontrol.IFocusListener;
 
 /**
@@ -42,6 +43,17 @@
     oneway void onAudioFocusChange(in String usage, in int zoneId, in AudioFocusChange focusChange);
 
     /**
+     * Notifies HAL of changes in output devices that the HAL should apply ducking to.
+     *
+     * This will be called in response to changes in audio focus, and will include a
+     * {@link DuckingInfo} object per audio zone that experienced a change in audo focus.
+     *
+     * @param duckingInfos an array of {@link DuckingInfo} objects for the audio zones where audio
+     * focus has changed.
+     */
+     oneway void onDevicesToDuckChange(in DuckingInfo[] duckingInfos);
+
+    /**
      * Registers focus listener to be used by HAL for requesting and abandoning audio focus.
      *
      * It is expected that there will only ever be a single focus listener registered. If the
diff --git a/automotive/audiocontrol/aidl/default/AudioControl.cpp b/automotive/audiocontrol/aidl/default/AudioControl.cpp
index 5e09b4f..748947c 100644
--- a/automotive/audiocontrol/aidl/default/AudioControl.cpp
+++ b/automotive/audiocontrol/aidl/default/AudioControl.cpp
@@ -17,6 +17,7 @@
 #include "AudioControl.h"
 
 #include <aidl/android/hardware/automotive/audiocontrol/AudioFocusChange.h>
+#include <aidl/android/hardware/automotive/audiocontrol/DuckingInfo.h>
 #include <aidl/android/hardware/automotive/audiocontrol/IFocusListener.h>
 
 #include <android-base/logging.h>
@@ -102,6 +103,27 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus AudioControl::onDevicesToDuckChange(
+        const std::vector<DuckingInfo>& in_duckingInfos) {
+    LOG(INFO) << "AudioControl::onDevicesToDuckChange";
+    for (const DuckingInfo& duckingInfo : in_duckingInfos) {
+        LOG(INFO) << "zone: " << duckingInfo.zoneId;
+        LOG(INFO) << "Devices to duck:";
+        for (auto& addressToDuck : duckingInfo.deviceAddressesToDuck) {
+            LOG(INFO) << addressToDuck;
+        }
+        LOG(INFO) << "Devices to unduck:";
+        for (auto& addressToUnduck : duckingInfo.deviceAddressesToUnduck) {
+            LOG(INFO) << addressToUnduck;
+        }
+        LOG(INFO) << "Usages holding focus:";
+        for (auto& usage : duckingInfo.usagesHoldingFocus) {
+            LOG(INFO) << usage;
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
 binder_status_t AudioControl::dump(int fd, const char** args, uint32_t numArgs) {
     if (numArgs == 0) {
         return dumpsys(fd);
diff --git a/automotive/audiocontrol/aidl/default/AudioControl.h b/automotive/audiocontrol/aidl/default/AudioControl.h
index a77da3e..cf56947 100644
--- a/automotive/audiocontrol/aidl/default/AudioControl.h
+++ b/automotive/audiocontrol/aidl/default/AudioControl.h
@@ -18,6 +18,7 @@
 
 #include <aidl/android/hardware/automotive/audiocontrol/AudioFocusChange.h>
 #include <aidl/android/hardware/automotive/audiocontrol/BnAudioControl.h>
+#include <aidl/android/hardware/automotive/audiocontrol/DuckingInfo.h>
 
 namespace aidl::android::hardware::automotive::audiocontrol {
 
@@ -27,6 +28,8 @@
   public:
     ndk::ScopedAStatus onAudioFocusChange(const std::string& in_usage, int32_t in_zoneId,
                                           AudioFocusChange in_focusChange) override;
+    ndk::ScopedAStatus onDevicesToDuckChange(
+            const std::vector<DuckingInfo>& in_duckingInfos) override;
     ndk::ScopedAStatus registerFocusListener(
             const shared_ptr<IFocusListener>& in_listener) override;
     ndk::ScopedAStatus setBalanceTowardRight(float in_value) override;
diff --git a/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp b/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp
index f33b8a5..f23280d 100644
--- a/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp
+++ b/automotive/audiocontrol/aidl/vts/VtsHalAudioControlTargetTest.cpp
@@ -31,6 +31,7 @@
 using android::binder::Status;
 using android::hardware::automotive::audiocontrol::AudioFocusChange;
 using android::hardware::automotive::audiocontrol::BnFocusListener;
+using android::hardware::automotive::audiocontrol::DuckingInfo;
 using android::hardware::automotive::audiocontrol::IAudioControl;
 
 #include "android_audio_policy_configuration_V7_0.h"
@@ -129,6 +130,22 @@
             audioControl->onAudioFocusChange(usage, 0, AudioFocusChange::GAIN_TRANSIENT).isOk());
 };
 
+TEST_P(AudioControlAidl, DuckChangeExercise) {
+    ALOGI("Duck change test");
+
+    DuckingInfo duckingInfo;
+    duckingInfo.zoneId = 0;
+    duckingInfo.deviceAddressesToDuck = {String16("address 1"), String16("address 2")};
+    duckingInfo.deviceAddressesToUnduck = {String16("address 3"), String16("address 4")};
+    duckingInfo.usagesHoldingFocus = {
+            String16(xsd::toString(xsd::AudioUsage::AUDIO_USAGE_MEDIA).c_str()),
+            String16(xsd::toString(xsd::AudioUsage::AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
+                             .c_str())};
+    std::vector<DuckingInfo> duckingInfos = {duckingInfo};
+    ALOGI("Duck change test start");
+    ASSERT_TRUE(audioControl->onDevicesToDuckChange(duckingInfos).isOk());
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioControlAidl);
 INSTANTIATE_TEST_SUITE_P(
         Audiocontrol, AudioControlAidl,