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

Commit 41d97463 authored by Jungshik Jang's avatar Jungshik Jang
Browse files

Add volume callback for Hdmi-Cec system audio mode.

Hdmi-Cec's system audio mode delegates audio control to
audio receiver from tv. It requires to delegate
volume change including mute to audio receiver
instead of consuming by tv.
In order to do this this change introduces three apis.
One is added to IAudioService, the others are added
to IHdmiControlService as hidden apis.

 1. IAudioService#setHdmiSystemAudioSupported;
    This is to notify system audio mode change to audio
    service so that it determines to notify volume or mute
    change to HdmiControlService.

 2. IHdmiControlService#setSystemAudioVolume;
    This is to notify volume change to HdmiControlService.
    It's called only where system audio mode is on.

 3. IHdmiControlService#setSystemAudioMute;
    This is to notify volume change to HdmiControlService .
    It's called only where system audio mode is on.

Change-Id: I3d8534b37ddf1a812e32012059a8778772044bf0
parent 70d34bb4
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -69,6 +69,34 @@ public final class HdmiTvClient {
        }
    }

    /**
     * Set system audio volume
     *
     * @param oldIndex current volume index
     * @param newIndex volume index to be set
     * @param maxIndex maximum volume index
     */
    public void setSystemAudioVolume(int oldIndex, int newIndex, int maxIndex) {
        try {
            mService.setSystemAudioVolume(oldIndex, newIndex, maxIndex);
        } catch (RemoteException e) {
            Log.e(TAG, "failed to set volume: ", e);
        }
    }

    /**
     * Set system audio mute status
     *
     * @param mute {@code true} if muted; otherwise, {@code false}
     */
    public void setSystemAudioMute(boolean mute) {
        try {
            mService.setSystemAudioMute(mute);
        } catch (RemoteException e) {
            Log.e(TAG, "failed to set mute: ", e);
        }
    }

    private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) {
        return new IHdmiControlCallback.Stub() {
            @Override
+2 −0
Original line number Diff line number Diff line
@@ -51,4 +51,6 @@ interface IHdmiControlService {
    void setControlEnabled(boolean enabled);
    void setArcMode(boolean enabled);
    void setOption(int option, int value);
    oneway void setSystemAudioVolume(int oldIndex, int newIndex, int maxIndex);
    oneway void setSystemAudioMute(boolean mute);
}
+23 −0
Original line number Diff line number Diff line
@@ -339,6 +339,12 @@ public class AudioManager {
     */
    public static final int FLAG_SHOW_SILENT_HINT = 1 << 7;

    /**
     * Indicates the volume call is for Hdmi Cec system audio volume
     * @hide
     */
    public static final int FLAG_HDMI_SYSTEM_AUDIO_VOLUME = 1 << 8;

    /**
     * Ringer mode that will be silent and will not vibrate. (This overrides the
     * vibrate setting.)
@@ -2872,6 +2878,23 @@ public class AudioManager {
        }
    }

    /**
     * Set Hdmi Cec system audio mode.
     *
     * @param on whether to be on system audio mode
     * @param device out device type to be used for system audio mode.
     *               Ignored if {@code on} is {@code false}
     * @param name name of system audio device
     * @hide
     */
    public void setHdmiSystemAudioSupported(boolean on, int device, String name) {
        try {
            getService().setHdmiSystemAudioSupported(on, device, name);
        } catch (RemoteException e) {
            Log.w(TAG, "Error setting system audio mode", e);
        }
    }

    /**
     * Return codes for listAudioPorts(), createAudioPatch() ...
     */
+100 −0
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.database.ContentObserver;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiTvClient;
import android.hardware.usb.UsbManager;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
@@ -572,6 +574,11 @@ public class AudioService extends IAudioService.Stub {
            setRotationForAudioSystem();
        }

        HdmiControlManager hdmiManager =
                (HdmiControlManager) mContext.getSystemService(Context.HDMI_CONTROL_SERVICE);
        // Null if device is not Tv.
        mHdmiTvClient = hdmiManager.getTvClient();

        context.registerReceiver(mReceiver, intentFilter);

        mUseMasterVolume = context.getResources().getBoolean(
@@ -969,6 +976,21 @@ public class AudioService extends IAudioService.Stub {
                        streamState,
                        0);
            }

            // Check if volume update should be send to Hdmi system audio.
            int newIndex = mStreamStates[streamType].getIndex(device);
            if (mHdmiTvClient != null &&
                streamTypeAlias == AudioSystem.STREAM_MUSIC &&
                (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0 &&
                oldIndex != newIndex) {
                int maxIndex = getStreamMaxVolume(streamType);
                synchronized (mHdmiTvClient) {
                    if (mHdmiSystemAudioSupported) {
                        mHdmiTvClient.setSystemAudioVolume(
                                (oldIndex + 5) / 10, (newIndex + 5) / 10, maxIndex);
                    }
                }
            }
        }
        int index = mStreamStates[streamType].getIndex(device);
        sendVolumeUpdate(streamType, oldIndex, index, flags);
@@ -1069,6 +1091,19 @@ public class AudioService extends IAudioService.Stub {
                }
            }

            if (mHdmiTvClient != null &&
                streamTypeAlias == AudioSystem.STREAM_MUSIC &&
                (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0 &&
                oldIndex != index) {
                int maxIndex = getStreamMaxVolume(streamType);
                synchronized (mHdmiTvClient) {
                    if (mHdmiSystemAudioSupported) {
                        mHdmiTvClient.setSystemAudioVolume(
                                (oldIndex + 5) / 10, (index + 5) / 10, maxIndex);
                    }
                }
            }

            flags &= ~AudioManager.FLAG_FIXED_VOLUME;
            if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
                    ((device & mFixedVolumeDevices) != 0)) {
@@ -1292,6 +1327,13 @@ public class AudioService extends IAudioService.Stub {
        }

        if (isStreamAffectedByMute(streamType)) {
            if (streamType == AudioSystem.STREAM_MUSIC && mHdmiTvClient != null) {
                synchronized (mHdmiTvClient) {
                    if (mHdmiSystemAudioSupported) {
                        mHdmiTvClient.setSystemAudioMute(state);
                    }
                }
            }
            mStreamStates[streamType].mute(cb, state);
        }
    }
@@ -4701,6 +4743,64 @@ public class AudioService extends IAudioService.Stub {
        }
    }

    //==========================================================================================
    // Hdmi Cec system audio mode.
    // If Hdmi Cec's system audio mode is on, audio service should notify volume change
    // to HdmiControlService so that audio recevier can handle volume change.
    //==========================================================================================

    // If HDMI-CEC system audio is supported
    private boolean mHdmiSystemAudioSupported = false;
    // Set only when device is tv.
    private HdmiTvClient mHdmiTvClient;

    @Override
    public void setHdmiSystemAudioSupported(boolean on, int device, String name) {
        if (mHdmiTvClient == null) {
            Log.w(TAG, "Only Hdmi-Cec enabled TV device supports system audio mode.");
            return;
        }

        if ((device & AudioSystem.DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO) == 0) {
            Log.w(TAG, "Unsupported Hdmi-Cec system audio output:" + device);
            return;
        }

        VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
        int oldStreamDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC);
        int oldIndex = streamState.getIndex(oldStreamDevice);

        synchronized (mHdmiTvClient) {
            mHdmiSystemAudioSupported = on;

            // TODO: call AudioSystem.setForceUse(FORCE_FOR_MEDIA,
            //         on ? AudioSystem.FORCE_SYSTEM_AUDIO_XXX : AudioSystem.FORCE_NONE;
        }

        int newStreamDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC);
        boolean updateSpeakerVolume = false;
        if (on) {
            if ((oldStreamDevice & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
                // Mute tv speaker. Note that set volume 0 instead of call mute() method because
                // it's not possible to mute for a specific device.
                streamState.setIndex(0, AudioSystem.DEVICE_OUT_SPEAKER);
                updateSpeakerVolume = true;
            }
        } else {
            if ((newStreamDevice & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
                // Restore speaker volume if exists. As there is no way to mute a device here,
                // load system audio's volume and set it to speaker.
                streamState.setIndex(oldIndex, AudioSystem.DEVICE_OUT_SPEAKER);
                updateSpeakerVolume = true;
            }
        }

        if (updateSpeakerVolume) {
            sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
                    AudioSystem.DEVICE_OUT_SPEAKER, 0,
                    streamState, 0);
        }
    }

    //==========================================================================================
    // Camera shutter sound policy.
+3 −0
Original line number Diff line number Diff line
@@ -287,6 +287,9 @@ public class AudioSystem
                                                  DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
    public static final int DEVICE_OUT_ALL_USB = (DEVICE_OUT_USB_ACCESSORY |
                                                  DEVICE_OUT_USB_DEVICE);
    public static final int DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO = (DEVICE_OUT_LINE |
                                                                DEVICE_OUT_HDMI_ARC |
                                                                DEVICE_OUT_SPDIF);

    // input devices
    public static final int DEVICE_IN_COMMUNICATION = DEVICE_BIT_IN | 0x1;
Loading