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

Commit 6f3a98be authored by Paul Colta's avatar Paul Colta
Browse files

HDMICEC: Dynamic soundbar mode feature

This feature gives users of STB/OTT devices with built-in or connected speakers the possibility to use it as a proper soundbar for the audio of the TV or other connected devices, supporting the main CEC functionalities for soundbars.

Bug: 237275185
Test: make && atest com.android.server.hdmi
Change-Id: I919eb3c75a89599135d3bb6bf52f0a4488e51dcf
parent 3170042b
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -4173,6 +4173,7 @@ package android.hardware.hdmi {
    method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public String getPowerStateChangeOnActiveSourceLost();
    method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public int getRoutingControl();
    method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public int getSadPresenceInQuery(@NonNull String);
    method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public int getSoundbarMode();
    method @Nullable public android.hardware.hdmi.HdmiSwitchClient getSwitchClient();
    method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public int getSystemAudioControl();
    method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public int getSystemAudioModeMuting();
@@ -4194,6 +4195,7 @@ package android.hardware.hdmi {
    method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setRoutingControl(@NonNull int);
    method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setSadPresenceInQuery(@NonNull String, int);
    method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setSadsPresenceInQuery(@NonNull java.util.List<java.lang.String>, int);
    method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setSoundbarMode(int);
    method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setStandbyMode(boolean);
    method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setSystemAudioControl(@NonNull int);
    method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setSystemAudioModeMuting(@NonNull int);
@@ -4221,6 +4223,7 @@ package android.hardware.hdmi {
    field public static final String CEC_SETTING_NAME_QUERY_SAD_TRUEHD = "query_sad_truehd";
    field public static final String CEC_SETTING_NAME_QUERY_SAD_WMAPRO = "query_sad_wmapro";
    field public static final String CEC_SETTING_NAME_ROUTING_CONTROL = "routing_control";
    field public static final String CEC_SETTING_NAME_SOUNDBAR_MODE = "soundbar_mode";
    field public static final String CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL = "system_audio_control";
    field public static final String CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING = "system_audio_mode_muting";
    field public static final String CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP = "tv_send_standby_on_sleep";
@@ -4302,6 +4305,8 @@ package android.hardware.hdmi {
    field public static final int ROUTING_CONTROL_DISABLED = 0; // 0x0
    field public static final int ROUTING_CONTROL_ENABLED = 1; // 0x1
    field public static final String SETTING_NAME_EARC_ENABLED = "earc_enabled";
    field public static final int SOUNDBAR_MODE_DISABLED = 0; // 0x0
    field public static final int SOUNDBAR_MODE_ENABLED = 1; // 0x1
    field public static final int SYSTEM_AUDIO_CONTROL_DISABLED = 0; // 0x0
    field public static final int SYSTEM_AUDIO_CONTROL_ENABLED = 1; // 0x1
    field public static final int SYSTEM_AUDIO_MODE_MUTING_DISABLED = 0; // 0x0
+92 −1
Original line number Diff line number Diff line
@@ -398,6 +398,30 @@ public final class HdmiControlManager {
    @Retention(RetentionPolicy.SOURCE)
    public @interface RoutingControl {}

    // -- Whether the Soundbar mode feature is enabled or disabled.
    /**
     * Soundbar mode feature enabled.
     *
     * @see HdmiControlManager#CEC_SETTING_NAME_SOUNDBAR_MODE
     */
    public static final int SOUNDBAR_MODE_ENABLED = 1;
    /**
     * Soundbar mode feature disabled.
     *
     * @see HdmiControlManager#CEC_SETTING_NAME_SOUNDBAR_MODE
     */
    public static final int SOUNDBAR_MODE_DISABLED = 0;
    /**
     * @see HdmiControlManager#CEC_SETTING_NAME_SOUNDBAR_MODE
     * @hide
     */
    @IntDef(prefix = { "SOUNDBAR_MODE" }, value = {
            SOUNDBAR_MODE_ENABLED,
            SOUNDBAR_MODE_DISABLED
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface SoundbarMode {}

    // -- Scope of CEC power control messages sent by a playback device.
    /**
     * Send CEC power control messages to TV only:
@@ -819,6 +843,14 @@ public final class HdmiControlManager {
     * @see HdmiControlManager#setRoutingControl(int)
     */
    public static final String CEC_SETTING_NAME_ROUTING_CONTROL = "routing_control";
    /**
     * Name of a setting deciding whether the Soundbar mode feature is enabled.
     * Before exposing this setting make sure the hardware supports it, otherwise, you may
     * experience multiple issues.
     *
     * @see HdmiControlManager#setSoundbarMode(int)
     */
    public static final String CEC_SETTING_NAME_SOUNDBAR_MODE = "soundbar_mode";
    /**
     * Name of a setting deciding on the power control mode.
     *
@@ -1070,6 +1102,8 @@ public final class HdmiControlManager {
    @StringDef(value = {
        CEC_SETTING_NAME_HDMI_CEC_ENABLED,
        CEC_SETTING_NAME_HDMI_CEC_VERSION,
        CEC_SETTING_NAME_ROUTING_CONTROL,
        CEC_SETTING_NAME_SOUNDBAR_MODE,
        CEC_SETTING_NAME_POWER_CONTROL_MODE,
        CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
        CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL,
@@ -1222,7 +1256,16 @@ public final class HdmiControlManager {
            case HdmiDeviceInfo.DEVICE_PLAYBACK:
                return mHasPlaybackDevice ? new HdmiPlaybackClient(mService) : null;
            case HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM:
                return mHasAudioSystemDevice ? new HdmiAudioSystemClient(mService) : null;
                try {
                    if ((mService.getCecSettingIntValue(CEC_SETTING_NAME_SOUNDBAR_MODE)
                            == SOUNDBAR_MODE_ENABLED && mHasPlaybackDevice)
                            || mHasAudioSystemDevice) {
                        return new HdmiAudioSystemClient(mService);
                    }
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
                return null;
            case HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH:
                return (mHasSwitchDevice || mIsSwitchDevice)
                    ? new HdmiSwitchClient(mService) : null;
@@ -2289,6 +2332,54 @@ public final class HdmiControlManager {
        }
    }

    /**
     * Set the status of Soundbar mode feature.
     *
     * <p>This allows to enable/disable Soundbar mode on the playback device.
     * The setting's effect will be available on devices where the hardware supports this feature.
     * If enabled, an audio system local device will be allocated and try to establish an ARC
     * connection with the TV. If disabled, the ARC connection will be terminated and the audio
     * system local device will be removed from the network.
     *
     * @see HdmiControlManager#CEC_SETTING_NAME_SOUNDBAR_MODE
     */
    @RequiresPermission(android.Manifest.permission.HDMI_CEC)
    public void setSoundbarMode(@SoundbarMode int value) {
        if (mService == null) {
            Log.e(TAG, "setSoundbarMode: HdmiControlService is not available");
            throw new RuntimeException("HdmiControlService is not available");
        }
        try {
            mService.setCecSettingIntValue(CEC_SETTING_NAME_SOUNDBAR_MODE, value);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Get the current status of Soundbar mode feature.
     *
     * <p>Reflects whether Soundbar mode is currently enabled on the playback device.
     * If enabled, an audio system local device will be allocated and try to establish an ARC
     * connection with the TV. If disabled, the ARC connection will be terminated and the audio
     * system local device will be removed from the network.
     *
     * @see HdmiControlManager#CEC_SETTING_NAME_SOUNDBAR_MODE
     */
    @SoundbarMode
    @RequiresPermission(android.Manifest.permission.HDMI_CEC)
    public int getSoundbarMode() {
        if (mService == null) {
            Log.e(TAG, "getSoundbarMode: HdmiControlService is not available");
            throw new RuntimeException("HdmiControlService is not available");
        }
        try {
            return mService.getCecSettingIntValue(CEC_SETTING_NAME_SOUNDBAR_MODE);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Set the status of Power Control.
     *
+6 −0
Original line number Diff line number Diff line
@@ -5354,6 +5354,12 @@
    <bool name="config_cecRoutingControlDisabled_allowed">true</bool>
    <bool name="config_cecRoutingControlDisabled_default">true</bool>

    <bool name="config_cecSoundbarMode_userConfigurable">true</bool>
    <bool name="config_cecSoundbarModeEnabled_allowed">true</bool>
    <bool name="config_cecSoundbarModeEnabled_default">false</bool>
    <bool name="config_cecSoundbarModeDisabled_allowed">true</bool>
    <bool name="config_cecSoundbarModeDisabled_default">true</bool>

    <bool name="config_cecPowerControlMode_userConfigurable">true</bool>
    <bool name="config_cecPowerControlModeTv_allowed">true</bool>
    <bool name="config_cecPowerControlModeTv_default">false</bool>
+6 −0
Original line number Diff line number Diff line
@@ -4556,6 +4556,12 @@
  <java-symbol type="bool" name="config_cecRoutingControlDisabled_allowed" />
  <java-symbol type="bool" name="config_cecRoutingControlDisabled_default" />

  <java-symbol type="bool" name="config_cecSoundbarMode_userConfigurable" />
  <java-symbol type="bool" name="config_cecSoundbarModeEnabled_allowed" />
  <java-symbol type="bool" name="config_cecSoundbarModeEnabled_default" />
  <java-symbol type="bool" name="config_cecSoundbarModeDisabled_allowed" />
  <java-symbol type="bool" name="config_cecSoundbarModeDisabled_default" />

  <java-symbol type="bool" name="config_cecPowerControlMode_userConfigurable" />
  <java-symbol type="bool" name="config_cecPowerControlModeTv_allowed" />
  <java-symbol type="bool" name="config_cecPowerControlModeTv_default" />
+18 −0
Original line number Diff line number Diff line
@@ -7180,6 +7180,24 @@ public class AudioService extends IAudioService.Stub
                        state == CONNECTION_STATE_CONNECTED ? "connected" : "disconnected")
                .record();
        mDeviceBroker.setWiredDeviceConnectionState(attributes, state, caller);
        // The Dynamic Soundbar mode feature introduces dynamic presence for an HDMI Audio System
        // Client. For example, the device can start with the Audio System Client unavailable.
        // When the feature is activated the client becomes available, therefore Audio Service
        // requests a new HDMI Audio System Client instance when the ARC status is changed.
        if (attributes.getInternalType() == AudioSystem.DEVICE_IN_HDMI_ARC) {
            updateHdmiAudioSystemClient();
        }
    }
    /**
     * Replace the current HDMI Audio System Client.
     * See {@link #setWiredDeviceConnectionState(AudioDeviceAttributes, int, String)}.
     */
    private void updateHdmiAudioSystemClient() {
        Slog.d(TAG, "Hdmi Audio System Client is updated");
        synchronized (mHdmiClientLock) {
            mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
        }
    }
    /** @see AudioManager#setTestDeviceConnectionState(AudioDeviceAttributes, boolean) */
Loading