Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f884979 authored by Mikhail Naganov's avatar Mikhail Naganov Committed by Gerrit Code Review
Browse files

Merge "audio: Implement ITelephony core interface for telecom"

parents f131f462 a7f4e053
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -36,4 +36,21 @@ package android.hardware.audio.core;
interface ITelephony {
  android.hardware.audio.core.AudioMode[] getSupportedAudioModes();
  void switchAudioMode(android.hardware.audio.core.AudioMode mode);
  android.hardware.audio.core.ITelephony.TelecomConfig setTelecomConfig(in android.hardware.audio.core.ITelephony.TelecomConfig config);
  @JavaDerive(equals=true, toString=true) @VintfStability
  parcelable TelecomConfig {
    @nullable android.media.audio.common.Float voiceVolume;
    android.hardware.audio.core.ITelephony.TelecomConfig.TtyMode ttyMode = android.hardware.audio.core.ITelephony.TelecomConfig.TtyMode.UNSPECIFIED;
    @nullable android.media.audio.common.Boolean isHacEnabled;
    const int VOICE_VOLUME_MIN = 0;
    const int VOICE_VOLUME_MAX = 1;
    @Backing(type="int") @VintfStability
    enum TtyMode {
      UNSPECIFIED = (-1),
      OFF = 0,
      FULL = 1,
      HCO = 2,
      VCO = 3,
    }
  }
}
+73 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package android.hardware.audio.core;

import android.hardware.audio.core.AudioMode;
import android.media.audio.common.Boolean;
import android.media.audio.common.Float;

/**
 * An instance of ITelephony manages settings which are specific to voice calls
@@ -53,4 +55,75 @@ interface ITelephony {
     * @throws EX_ILLEGAL_STATE If there was an error during switching.
     */
    void switchAudioMode(AudioMode mode);

    @JavaDerive(equals=true, toString=true)
    @VintfStability
    parcelable TelecomConfig {
        const int VOICE_VOLUME_MIN = 0;
        const int VOICE_VOLUME_MAX = 1;
        /**
         * Volume of a voice call. 1.0f means unity gain, 0.0f is muted,
         * see VOLUME_* constants.
         */
        @nullable Float voiceVolume;
        /**
         * The current mode of teletypewritter (TTY).
         */
        @VintfStability
        @Backing(type="int")
        enum TtyMode {
            /**
             * The default uninitialized value.
             */
            UNSPECIFIED = -1,
            /**
             * TTY mode is off.
             */
            OFF = 0,
            /**
             * TTY mode is on. The speaker is off and the microphone is muted. The
             * user will communicate with the remote party by sending and receiving
             * text messages.
             */
            FULL = 1,
            /**
             * TTY mode is in hearing carryover mode (HCO). The microphone is muted
             * but the speaker is on. The user will communicate with the remote
             * party by sending text messages and hearing an audible reply.
             */
            HCO = 2,
            /**
             * TTY mode is in voice carryover mode (VCO). The speaker is off but the
             * microphone is still on. User will communicate with the remote party
             * by speaking and receiving text message replies.
             */
            VCO = 3,
        }
        TtyMode ttyMode = TtyMode.UNSPECIFIED;
        /**
         * Whether Hearing Aid Compatibility - Telecoil (HAC-T) mode is enabled.
         */
        @nullable Boolean isHacEnabled;
    }

    /**
     * Set the configuration of the telephony audio.
     *
     * In the provided parcelable, the client sets zero, one or more parameters
     * which have to be updated on the HAL side. The parameters that are left
     * unset must retain their current values.
     *
     * In the returned parcelable, all parameter fields known to the HAL module
     * must be populated to their current values.The client can pass an
     * uninitialized parcelable in order to retrieve the current configuration.
     *
     * @return The current configuration (after update). All fields known to
     *         the HAL must be populated.
     * @param config The configuration to set. Any number of fields may be left
     *               uninitialized.
     * @throws EX_UNSUPPORTED_OPERATION If telephony is not supported.
     * @throws EX_ILLEGAL_ARGUMENT If the requested combination of parameter
     *                             values is invalid.
     */
    TelecomConfig setTelecomConfig(in TelecomConfig config);
}
+33 −0
Original line number Diff line number Diff line
@@ -20,8 +20,17 @@

#include "core-impl/Telephony.h"

using aidl::android::media::audio::common::Boolean;
using aidl::android::media::audio::common::Float;

namespace aidl::android::hardware::audio::core {

Telephony::Telephony() {
    mTelecomConfig.voiceVolume = Float{TelecomConfig::VOICE_VOLUME_MAX};
    mTelecomConfig.ttyMode = TelecomConfig::TtyMode::OFF;
    mTelecomConfig.isHacEnabled = Boolean{false};
}

ndk::ScopedAStatus Telephony::getSupportedAudioModes(std::vector<AudioMode>* _aidl_return) {
    *_aidl_return = mSupportedAudioModes;
    LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
@@ -38,4 +47,28 @@ ndk::ScopedAStatus Telephony::switchAudioMode(AudioMode in_mode) {
    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}

ndk::ScopedAStatus Telephony::setTelecomConfig(const TelecomConfig& in_config,
                                               TelecomConfig* _aidl_return) {
    if (in_config.voiceVolume.has_value() &&
        (in_config.voiceVolume.value().value < TelecomConfig::VOICE_VOLUME_MIN ||
         in_config.voiceVolume.value().value > TelecomConfig::VOICE_VOLUME_MAX)) {
        LOG(ERROR) << __func__
                   << ": voice volume value is invalid: " << in_config.voiceVolume.value().value;
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
    }
    if (in_config.voiceVolume.has_value()) {
        mTelecomConfig.voiceVolume = in_config.voiceVolume;
    }
    if (in_config.ttyMode != TelecomConfig::TtyMode::UNSPECIFIED) {
        mTelecomConfig.ttyMode = in_config.ttyMode;
    }
    if (in_config.isHacEnabled.has_value()) {
        mTelecomConfig.isHacEnabled = in_config.isHacEnabled;
    }
    *_aidl_return = mTelecomConfig;
    LOG(DEBUG) << __func__ << ": received " << in_config.toString() << ", returning "
               << _aidl_return->toString();
    return ndk::ScopedAStatus::ok();
}

}  // namespace aidl::android::hardware::audio::core
+6 −0
Original line number Diff line number Diff line
@@ -23,12 +23,18 @@
namespace aidl::android::hardware::audio::core {

class Telephony : public BnTelephony {
  public:
    Telephony();

  private:
    ndk::ScopedAStatus getSupportedAudioModes(std::vector<AudioMode>* _aidl_return) override;
    ndk::ScopedAStatus switchAudioMode(AudioMode in_mode) override;
    ndk::ScopedAStatus setTelecomConfig(const TelecomConfig& in_config,
                                        TelecomConfig* _aidl_return) override;

    const std::vector<AudioMode> mSupportedAudioModes = {::ndk::enum_range<AudioMode>().begin(),
                                                         ::ndk::enum_range<AudioMode>().end()};
    TelecomConfig mTelecomConfig;
};

}  // namespace aidl::android::hardware::audio::core
+41 −0
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ using aidl::android::media::audio::common::AudioPortDeviceExt;
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioSource;
using aidl::android::media::audio::common::AudioUsage;
using aidl::android::media::audio::common::Float;
using aidl::android::media::audio::common::Void;
using android::hardware::audio::common::getChannelCount;
using android::hardware::audio::common::isBitPositionFlagSet;
@@ -1828,6 +1829,46 @@ TEST_P(AudioCoreTelephony, SwitchAudioMode) {
    }
}

TEST_P(AudioCoreTelephony, TelecomConfig) {
    static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
    if (telephony == nullptr) {
        GTEST_SKIP() << "Telephony is not supported";
    }
    ndk::ScopedAStatus status;
    ITelephony::TelecomConfig telecomConfig;
    ASSERT_STATUS(kStatuses, status = telephony->setTelecomConfig({}, &telecomConfig));
    if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
        GTEST_SKIP() << "Telecom is not supported";
    }
    EXPECT_TRUE(telecomConfig.voiceVolume.has_value());
    EXPECT_NE(ITelephony::TelecomConfig::TtyMode::UNSPECIFIED, telecomConfig.ttyMode);
    EXPECT_TRUE(telecomConfig.isHacEnabled.has_value());
    ITelephony::TelecomConfig telecomConfig2;
    ASSERT_IS_OK(telephony->setTelecomConfig(telecomConfig, &telecomConfig2));
    EXPECT_EQ(telecomConfig, telecomConfig2);
}

TEST_P(AudioCoreTelephony, TelecomConfigInvalid) {
    static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
    if (telephony == nullptr) {
        GTEST_SKIP() << "Telephony is not supported";
    }
    ndk::ScopedAStatus status;
    ITelephony::TelecomConfig telecomConfig;
    ASSERT_STATUS(kStatuses, status = telephony->setTelecomConfig({}, &telecomConfig));
    if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
        GTEST_SKIP() << "Telecom is not supported";
    }
    EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
                  telephony->setTelecomConfig(
                          {.voiceVolume = Float{ITelephony::TelecomConfig::VOICE_VOLUME_MIN - 1}},
                          &telecomConfig));
    EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
                  telephony->setTelecomConfig(
                          {.voiceVolume = Float{ITelephony::TelecomConfig::VOICE_VOLUME_MAX + 1}},
                          &telecomConfig));
}

using CommandSequence = std::vector<StreamDescriptor::Command>;
class StreamLogicDriverInvalidCommand : public StreamLogicDriver {
  public: