audio: Add volume/mute, audio mode, and screen state to IModule

Add the following methods to IModule:
 - getTelephony;
 - get/setMasterMute;
 - get/setMasterVolume;
 - get/setMicMute;
 - updateAudioMode;
 - updateScreenRotation;
 - updateScreenState;
The "update..." methods are "informational," the HAL may ignore
them and must not raise any errors.

ITelephony currently contains 2 methods:
 - getSupportedAudioModes;
 - switchAudioMode.
This "switchAudioMode" must validate the argument, and must
switch the HAL to the new mode synchronously.

Implement and add VTS tests.

Bug: 205884982
Test: atest VtsHalAudioCoreTargetTest
Change-Id: I9174c81fe7d16f7068257051ae5e129b15e82648
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index d34d68c..676c7cf 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -39,6 +39,7 @@
         "Configuration.cpp",
         "Module.cpp",
         "Stream.cpp",
+        "Telephony.cpp",
     ],
     visibility: [
         ":__subpackages__",
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index deaca49..6863fe3 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -25,6 +25,7 @@
 #include <aidl/android/media/audio/common/AudioOutputFlags.h>
 
 #include "core-impl/Module.h"
+#include "core-impl/Telephony.h"
 #include "core-impl/utils.h"
 
 using aidl::android::hardware::audio::common::SinkMetadata;
@@ -245,6 +246,15 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Module::getTelephony(std::shared_ptr<ITelephony>* _aidl_return) {
+    if (mTelephony == nullptr) {
+        mTelephony = ndk::SharedRefBase::make<Telephony>();
+    }
+    *_aidl_return = mTelephony;
+    LOG(DEBUG) << __func__ << ": returning instance of ITelephony: " << _aidl_return->get();
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus Module::connectExternalDevice(const AudioPort& in_templateIdAndAdditionalData,
                                                  AudioPort* _aidl_return) {
     const int32_t templateId = in_templateIdAndAdditionalData.id;
@@ -779,4 +789,60 @@
     return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
 }
 
+ndk::ScopedAStatus Module::getMasterMute(bool* _aidl_return) {
+    *_aidl_return = mMasterMute;
+    LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::setMasterMute(bool in_mute) {
+    LOG(DEBUG) << __func__ << ": " << in_mute;
+    mMasterMute = in_mute;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::getMasterVolume(float* _aidl_return) {
+    *_aidl_return = mMasterVolume;
+    LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::setMasterVolume(float in_volume) {
+    LOG(DEBUG) << __func__ << ": " << in_volume;
+    if (in_volume >= 0.0f && in_volume <= 1.0f) {
+        mMasterVolume = in_volume;
+        return ndk::ScopedAStatus::ok();
+    }
+    LOG(ERROR) << __func__ << ": invalid master volume value: " << in_volume;
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+}
+
+ndk::ScopedAStatus Module::getMicMute(bool* _aidl_return) {
+    *_aidl_return = mMicMute;
+    LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::setMicMute(bool in_mute) {
+    LOG(DEBUG) << __func__ << ": " << in_mute;
+    mMicMute = in_mute;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::updateAudioMode(AudioMode in_mode) {
+    // No checks for supported audio modes here, it's an informative notification.
+    LOG(DEBUG) << __func__ << ": " << toString(in_mode);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::updateScreenRotation(ScreenRotation in_rotation) {
+    LOG(DEBUG) << __func__ << ": " << toString(in_rotation);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::updateScreenState(bool in_isTurnedOn) {
+    LOG(DEBUG) << __func__ << ": " << in_isTurnedOn;
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Telephony.cpp b/audio/aidl/default/Telephony.cpp
new file mode 100644
index 0000000..1854b35
--- /dev/null
+++ b/audio/aidl/default/Telephony.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#include <android/binder_to_string.h>
+#define LOG_TAG "AHAL_Telephony"
+#include <android-base/logging.h>
+
+#include "core-impl/Telephony.h"
+
+namespace aidl::android::hardware::audio::core {
+
+ndk::ScopedAStatus Telephony::getSupportedAudioModes(std::vector<AudioMode>* _aidl_return) {
+    *_aidl_return = mSupportedAudioModes;
+    LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Telephony::switchAudioMode(AudioMode in_mode) {
+    if (std::find(mSupportedAudioModes.begin(), mSupportedAudioModes.end(), in_mode) !=
+        mSupportedAudioModes.end()) {
+        LOG(DEBUG) << __func__ << ": " << toString(in_mode);
+        return ndk::ScopedAStatus::ok();
+    }
+    LOG(ERROR) << __func__ << ": unsupported mode " << toString(in_mode);
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+}  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 61516b2..0086743 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -35,6 +35,7 @@
   private:
     ndk::ScopedAStatus setModuleDebug(
             const ::aidl::android::hardware::audio::core::ModuleDebug& in_debug) override;
+    ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
     ndk::ScopedAStatus connectExternalDevice(
             const ::aidl::android::media::audio::common::AudioPort& in_templateIdAndAdditionalData,
             ::aidl::android::media::audio::common::AudioPort* _aidl_return) override;
@@ -70,6 +71,17 @@
             bool* _aidl_return) override;
     ndk::ScopedAStatus resetAudioPatch(int32_t in_patchId) override;
     ndk::ScopedAStatus resetAudioPortConfig(int32_t in_portConfigId) override;
+    ndk::ScopedAStatus getMasterMute(bool* _aidl_return) override;
+    ndk::ScopedAStatus setMasterMute(bool in_mute) override;
+    ndk::ScopedAStatus getMasterVolume(float* _aidl_return) override;
+    ndk::ScopedAStatus setMasterVolume(float in_volume) override;
+    ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
+    ndk::ScopedAStatus setMicMute(bool in_mute) override;
+    ndk::ScopedAStatus updateAudioMode(
+            ::aidl::android::hardware::audio::core::AudioMode in_mode) override;
+    ndk::ScopedAStatus updateScreenRotation(
+            ::aidl::android::hardware::audio::core::IModule::ScreenRotation in_rotation) override;
+    ndk::ScopedAStatus updateScreenState(bool in_isTurnedOn) override;
 
     void cleanUpPatch(int32_t patchId);
     ndk::ScopedAStatus createStreamContext(
@@ -88,12 +100,18 @@
 
     std::unique_ptr<internal::Configuration> mConfig;
     ModuleDebug mDebug;
+    // Since it is required to return the same instance of the ITelephony, even
+    // if the client has released it on its side, we need to hold it via a strong pointer.
+    std::shared_ptr<ITelephony> mTelephony;
     // ids of ports created at runtime via 'connectExternalDevice'.
     std::set<int32_t> mConnectedDevicePorts;
     Streams mStreams;
     // Maps port ids and port config ids to patch ids.
     // Multimap because both ports and configs can be used by multiple patches.
     std::multimap<int32_t, int32_t> mPatches;
+    bool mMasterMute = false;
+    float mMasterVolume = 1.0f;
+    bool mMicMute = false;
 };
 
 }  // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Telephony.h b/audio/aidl/default/include/core-impl/Telephony.h
new file mode 100644
index 0000000..597f3d6
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/Telephony.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#pragma once
+
+#include <android/binder_enums.h>
+
+#include <aidl/android/hardware/audio/core/BnTelephony.h>
+
+namespace aidl::android::hardware::audio::core {
+
+class Telephony : public BnTelephony {
+  private:
+    ndk::ScopedAStatus getSupportedAudioModes(std::vector<AudioMode>* _aidl_return) override;
+    ndk::ScopedAStatus switchAudioMode(AudioMode in_mode) override;
+
+    const std::vector<AudioMode> mSupportedAudioModes = {::ndk::enum_range<AudioMode>().begin(),
+                                                         ::ndk::enum_range<AudioMode>().end()};
+};
+
+}  // namespace aidl::android::hardware::audio::core