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

Commit ca17a902 authored by Wonsik Kim's avatar Wonsik Kim
Browse files

TIF: allow TIS to override default sink from audio policy

Bug: 16635576
Change-Id: I995cfca084950f96675aeb086c5055f76d1c4752
parent ae441287
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ interface ITvInputHardware {
     * trigger CEC commands for adjusting active HDMI source. Returns true on success.
     */
    boolean setSurface(in Surface surface, in TvStreamConfig config);

    /**
     * Set volume for this stream via AudioGain. (TBD)
     */
@@ -43,4 +44,21 @@ interface ITvInputHardware {
     * HDMI CEC commands. If the hardware is not representing an HDMI port, this method will fail.
     */
    boolean dispatchKeyEventToHdmi(in KeyEvent event);

    /**
     * Override default audio sink from audio policy. When override is on, it is
     * TvInputService's responsibility to adjust to audio configuration change
     * (for example, when the audio sink becomes unavailable or more desirable
     * audio sink is detected).
     *
     * @param audioType one of AudioManager.DEVICE_* values. When it's * DEVICE_NONE, override
     *        becomes off.
     * @param audioAddress audio address of the overriding device.
     * @param samplingRate desired sampling rate. Use default when it's 0.
     * @param channelMask desired channel mask. Use default when it's
     *        AudioFormat.CHANNEL_OUT_DEFAULT.
     * @param format desired format. Use default when it's AudioFormat.ENCODING_DEFAULT.
     */
    void overrideAudioSink(int audioType, String audioAddress, int samplingRate, int channelMask,
            int format);
}
+86 −33
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.hardware.hdmi.IHdmiDeviceEventListener;
import android.hardware.hdmi.IHdmiHotplugEventListener;
import android.hardware.hdmi.IHdmiInputChangeListener;
import android.media.AudioDevicePort;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioPatch;
import android.media.AudioPort;
@@ -556,41 +557,54 @@ class TvInputHardwareManager implements TvInputHal.Callback {
        private final Object mImplLock = new Object();

        private final AudioDevicePort mAudioSource;
        private final AudioDevicePort mAudioSink;
        private AudioDevicePort mAudioSink;
        private AudioPatch mAudioPatch = null;

        private TvStreamConfig mActiveConfig = null;

        private int mDesiredSamplingRate = 0;
        private int mDesiredChannelMask = AudioFormat.CHANNEL_OUT_DEFAULT;
        private int mDesiredFormat = AudioFormat.ENCODING_DEFAULT;

        public TvInputHardwareImpl(TvInputHardwareInfo info) {
            mInfo = info;
            AudioDevicePort audioSource = null;
            AudioDevicePort audioSink = null;
            if (mInfo.getAudioType() != AudioManager.DEVICE_NONE) {
                audioSource = findAudioDevicePort(mInfo.getAudioType(), mInfo.getAudioAddress());
                mAudioSink = findAudioSinkFromAudioPolicy();
            }
            mAudioSource = audioSource;
        }

        private AudioDevicePort findAudioSinkFromAudioPolicy() {
            ArrayList<AudioPort> devicePorts = new ArrayList<AudioPort>();
            if (mAudioManager.listAudioDevicePorts(devicePorts) == AudioManager.SUCCESS) {
                    // Find source
                int sinkDevice = mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC);
                for (AudioPort port : devicePorts) {
                    AudioDevicePort devicePort = (AudioDevicePort) port;
                        if (devicePort.type() == mInfo.getAudioType() &&
                                devicePort.address().equals(mInfo.getAudioAddress())) {
                            audioSource = devicePort;
                            break;
                    if (devicePort.type() == sinkDevice) {
                        return devicePort;
                    }
                }
                    // Find sink
                    // TODO: App may want to specify sink device?
                    int sinkDevices = mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC);
                    for (AudioPort port : devicePorts) {
                        AudioDevicePort devicePort = (AudioDevicePort) port;
                        if (devicePort.type() == sinkDevices) {
                            audioSink = devicePort;
                            break;
            }
            return null;
        }

        private AudioDevicePort findAudioDevicePort(int type, String address) {
            if (type == AudioManager.DEVICE_NONE) {
                return null;
            }
            ArrayList<AudioPort> devicePorts = new ArrayList<AudioPort>();
            if (mAudioManager.listAudioDevicePorts(devicePorts) != AudioManager.SUCCESS) {
                return null;
            }
            for (AudioPort port : devicePorts) {
                AudioDevicePort devicePort = (AudioDevicePort) port;
                if (devicePort.type() == type && devicePort.address().equals(address)) {
                    return devicePort;
                }
            }
            mAudioSource = audioSource;
            mAudioSink = audioSink;
            return null;
        }

        public void release() {
@@ -621,15 +635,7 @@ class TvInputHardwareManager implements TvInputHal.Callback {
                }
                if (mAudioSource != null && mAudioSink != null) {
                    if (surface != null) {
                        AudioPortConfig sourceConfig = mAudioSource.activeConfig();
                        AudioPortConfig sinkConfig = mAudioSink.activeConfig();
                        AudioPatch[] audioPatchArray = new AudioPatch[] { mAudioPatch };
                        // TODO: build config if activeConfig() == null
                        mAudioManager.createAudioPatch(
                                audioPatchArray,
                                new AudioPortConfig[] { sourceConfig },
                                new AudioPortConfig[] { sinkConfig });
                        mAudioPatch = audioPatchArray[0];
                        updateAudioPatchLocked();
                    } else {
                        mAudioManager.releaseAudioPatch(mAudioPatch);
                        mAudioPatch = null;
@@ -656,6 +662,31 @@ class TvInputHardwareManager implements TvInputHal.Callback {
            }
        }

        private void updateAudioPatchLocked() {
            AudioPortConfig sourceConfig = mAudioSource.activeConfig();
            AudioPortConfig sinkConfig = mAudioSink.activeConfig();
            AudioPatch[] audioPatchArray = new AudioPatch[] { mAudioPatch };
            if (sinkConfig == null
                    || (mDesiredSamplingRate != 0
                            && sinkConfig.samplingRate() != mDesiredSamplingRate)
                    || (mDesiredChannelMask != AudioFormat.CHANNEL_OUT_DEFAULT
                            && sinkConfig.channelMask() != mDesiredChannelMask)
                    || (mDesiredFormat != AudioFormat.ENCODING_DEFAULT
                            && sinkConfig.format() != mDesiredFormat)) {
                sinkConfig = mAudioSource.buildConfig(mDesiredSamplingRate, mDesiredChannelMask,
                        mDesiredFormat, null);
            }
            if (sourceConfig == null) {
                sourceConfig = mAudioSource.buildConfig(sinkConfig.samplingRate(),
                        sinkConfig.channelMask(), sinkConfig.format(), null);
            }
            mAudioManager.createAudioPatch(
                    audioPatchArray,
                    new AudioPortConfig[] { sourceConfig },
                    new AudioPortConfig[] { sinkConfig });
            mAudioPatch = audioPatchArray[0];
        }

        @Override
        public void setVolume(float volume) throws RemoteException {
            synchronized (mImplLock) {
@@ -710,6 +741,28 @@ class TvInputHardwareManager implements TvInputHal.Callback {
                return result == TvInputHal.SUCCESS;
            }
        }

        @Override
        public void overrideAudioSink(int audioType, String audioAddress, int samplingRate,
                int channelMask, int format) {
            synchronized (mImplLock) {
                if (audioType == AudioManager.DEVICE_NONE) {
                    mAudioSink = findAudioSinkFromAudioPolicy();
                } else {
                    AudioDevicePort audioSink = findAudioDevicePort(audioType, audioAddress);
                    if (audioSink != null) {
                        mAudioSink = audioSink;
                    }
                }
                mDesiredSamplingRate = samplingRate;
                mDesiredChannelMask = channelMask;
                mDesiredFormat = format;

                if (mAudioPatch != null) {
                    updateAudioPatchLocked();
                }
            }
        }
    }

    interface Listener {