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

Commit e9565df5 authored by Yan Han's avatar Yan Han
Browse files

Support "Mute" and "Restore Volume" CEC commands

Adds support for <User Control Pressed> ["Mute Function"] and ["Restore
Volume Function"] on all HDMI devices. These commands are currently
ignored because they are not mapped to an Android keycode.

Support for these commands is required for HDMI CEC 2.0.

Bug: 191230341
Test: Manual; atest HdmiCecLocalDeviceTest
Change-Id: I5146e9e99595a9a124e0ce2176f5e70a29923a49
parent 7182e9a3
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.input.InputManager;
import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.media.AudioManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -685,11 +686,29 @@ abstract class HdmiCecLocalDevice {
                    Message.obtain(mHandler, MSG_USER_CONTROL_RELEASE_TIMEOUT),
                    FOLLOWER_SAFETY_TIMEOUT);
            return Constants.HANDLED;
        } else if (params.length > 0) {
            // Handle CEC UI commands that are not mapped to an Android keycode
            return handleUnmappedCecKeycode(params[0]);
        }

        return Constants.ABORT_INVALID_OPERAND;
    }

    @ServiceThreadOnly
    @Constants.HandleMessageResult
    protected int handleUnmappedCecKeycode(int cecKeycode) {
        if (cecKeycode == HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION) {
            mService.getAudioManager().adjustStreamVolume(AudioManager.STREAM_MUSIC,
                    AudioManager.ADJUST_MUTE, AudioManager.FLAG_SHOW_UI);
            return Constants.HANDLED;
        } else if (cecKeycode == HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION) {
            mService.getAudioManager().adjustStreamVolume(AudioManager.STREAM_MUSIC,
                    AudioManager.ADJUST_UNMUTE, AudioManager.FLAG_SHOW_UI);
            return Constants.HANDLED;
        }
        return Constants.ABORT_INVALID_OPERAND;
    }

    @ServiceThreadOnly
    @Constants.HandleMessageResult
    protected int handleUserControlReleased() {
+39 −0
Original line number Diff line number Diff line
@@ -32,9 +32,15 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.content.Context;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPortInfo;
import android.media.AudioManager;
import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;

@@ -45,6 +51,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.ArrayList;
import java.util.Arrays;
@@ -123,8 +131,12 @@ public class HdmiCecLocalDeviceTest {
    private boolean isControlEnabled;
    private int mPowerStatus;

    @Mock
    private AudioManager mAudioManager;

    @Before
    public void SetUp() {
        MockitoAnnotations.initMocks(this);

        Context context = InstrumentationRegistry.getTargetContext();

@@ -161,6 +173,11 @@ public class HdmiCecLocalDeviceTest {
                    void wakeUp() {
                        mWakeupMessageReceived = true;
                    }

                    @Override
                    AudioManager getAudioManager() {
                        return mAudioManager;
                    }
                };
        mHdmiControlService.setIoLooper(mTestLooper.getLooper());
        mHdmiControlService.setHdmiCecConfig(new FakeHdmiCecConfig(context));
@@ -418,6 +435,28 @@ public class HdmiCecLocalDeviceTest {
        assertThat(mStandbyMessageReceived).isTrue();
    }

    @Test
    public void handleUserControlPressed_muteFunction() {
        @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
                        HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION));

        assertEquals(result, Constants.HANDLED);
        verify(mAudioManager, times(1))
                .adjustStreamVolume(anyInt(), eq(AudioManager.ADJUST_MUTE), anyInt());
    }

    @Test
    public void handleUserControlPressed_restoreVolumeFunction() {
        @Constants.HandleMessageResult int result = mHdmiLocalDevice.handleUserControlPressed(
                HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1,
                        HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION));

        assertEquals(result, Constants.HANDLED);
        verify(mAudioManager, times(1))
                .adjustStreamVolume(anyInt(), eq(AudioManager.ADJUST_UNMUTE), anyInt());
    }

    @Test
    public void handleVendorCommand_notHandled() {
        HdmiCecMessage vendorCommand = HdmiCecMessageBuilder.buildVendorCommand(ADDR_TV,