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

Commit e1469da8 authored by Sherry Huang's avatar Sherry Huang
Browse files

HDMI: Support Feature Discovery feature

HDMI 2.1a page 468 specifies that when a device makes an update to one
or more of the operands of the <Report Feature> message change value, it
shall braodcast a <Report Features> message with the up-to-date operand
values.
Note: Due to build issue with main branch, manual testing and cts for tv
device are verified with udc-tv-dev branch.

Bug: 296356402
Test: manual testing on ADT-4 and gambit; atest com.android.server.hdmi.HdmiControlServiceTest#setRcProfile[menu_name]_reportFeatureBroadcast and atest com.android.server.hdmi.HdmiControlServiceTvTest#setRcProfileTV_reportFeatureBroadcast
Change-Id: Ib42ffccb64bb9c5a8c9dc703042b035496b89f5d
parent f0694c53
Loading
Loading
Loading
Loading
+69 −0
Original line number Original line Diff line number Diff line
@@ -867,6 +867,60 @@ public class HdmiControlService extends SystemService {
                        }
                        }
                    }
                    }
                }, mServiceThreadExecutor);
                }, mServiceThreadExecutor);
        mHdmiCecConfig.registerChangeListener(HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_TV,
                new HdmiCecConfig.SettingChangeListener() {
                    @Override
                    public void onChange(String setting) {
                        reportFeatures(true);
                    }
                },
                mServiceThreadExecutor);
        mHdmiCecConfig.registerChangeListener(
                HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_ROOT_MENU,
                new HdmiCecConfig.SettingChangeListener() {
                    @Override
                    public void onChange(String setting) {
                        reportFeatures(false);
                    }
                },
                mServiceThreadExecutor);
        mHdmiCecConfig.registerChangeListener(
                HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_SETUP_MENU,
                new HdmiCecConfig.SettingChangeListener() {
                    @Override
                    public void onChange(String setting) {
                        reportFeatures(false);
                    }
                },
                mServiceThreadExecutor);
        mHdmiCecConfig.registerChangeListener(
                HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU,
                new HdmiCecConfig.SettingChangeListener() {
                    @Override
                    public void onChange(String setting) {
                        reportFeatures(false);
                    }
                },
                mServiceThreadExecutor);
        mHdmiCecConfig.registerChangeListener(
                HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_TOP_MENU,
                new HdmiCecConfig.SettingChangeListener() {
                    @Override
                    public void onChange(String setting) {
                        reportFeatures(false);
                    }
                },
                mServiceThreadExecutor);
        mHdmiCecConfig.registerChangeListener(
                HdmiControlManager
                        .CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU,
                new HdmiCecConfig.SettingChangeListener() {
                    @Override
                    public void onChange(String setting) {
                        reportFeatures(false);
                    }
                },
                mServiceThreadExecutor);


        if (isTvDevice()) {
        if (isTvDevice()) {
            mDeviceConfig.addOnPropertiesChangedListener(getContext().getMainExecutor(),
            mDeviceConfig.addOnPropertiesChangedListener(getContext().getMainExecutor(),
@@ -968,6 +1022,21 @@ public class HdmiControlService extends SystemService {
        }
        }
    }
    }


    /** Helper method for sending feature discovery command */
    private void reportFeatures(boolean isTvDeviceSetting) {
        // check if tv device is enabled for tv device specific RC profile setting
        if (isTvDeviceSetting) {
            if (isTvDeviceEnabled()) {
                tv().reportFeatures();
            }
        } else { // check for source device setting
            HdmiCecLocalDeviceSource source = isAudioSystemDevice() ? audioSystem() : playback();
            if (source != null) {
                source.reportFeatures();
            }
        }
    }

    /**
    /**
     * Returns the initial power status used when the HdmiControlService starts.
     * Returns the initial power status used when the HdmiControlService starts.
     */
     */
+54 −0
Original line number Original line Diff line number Diff line
@@ -407,6 +407,60 @@ public class HdmiControlServiceTest {
                HdmiControlManager.VOLUME_CONTROL_ENABLED);
                HdmiControlManager.VOLUME_CONTROL_ENABLED);
    }
    }


    @Test
    public void setRcProfileRootMenu_reportFeatureBroadcast() {
        setRcProfileSourceDeviceTestHelper(
                HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_ROOT_MENU,
                HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED);
    }

    @Test
    public void setRcProfileSetupMenu_reportFeatureBroadcast() {
        setRcProfileSourceDeviceTestHelper(
                HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_SETUP_MENU,
                HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED);
    }

    @Test
    public void setRcProfileContentMenu_reportFeatureBroadcast() {
        setRcProfileSourceDeviceTestHelper(
                HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU,
                HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED);
    }

    @Test
    public void setRcProfileTopMenu_reportFeatureBroadcast() {
        setRcProfileSourceDeviceTestHelper(
                HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_TOP_MENU,
                HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED);
    }

    @Test
    public void setRcProfileMediaSensitiveMenu_reportFeatureBroadcast() {
        setRcProfileSourceDeviceTestHelper(
                HdmiControlManager
                        .CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU,
                HdmiControlManager.RC_PROFILE_SOURCE_MENU_HANDLED);
    }

    /** Helper method to test if feature discovery message sent given RCProfile change */
    private void setRcProfileSourceDeviceTestHelper(final String setting, final int val) {
        mNativeWrapper.clearResultMessages();

        mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(
                HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
                HdmiControlManager.HDMI_CEC_VERSION_2_0);
        mHdmiControlServiceSpy.getHdmiCecConfig().setIntValue(setting, val);
        mTestLooper.dispatchAll();

        HdmiCecMessage reportFeatures = ReportFeaturesMessage.build(Constants.ADDR_PLAYBACK_1,
                HdmiControlManager.HDMI_CEC_VERSION_2_0,
                Arrays.asList(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM),
                mPlaybackDeviceSpy.getRcProfile(), mPlaybackDeviceSpy.getRcFeatures(),
                mPlaybackDeviceSpy.getDeviceFeatures());
        assertThat(mNativeWrapper.getResultMessages()).contains(reportFeatures);
    }

    @Test
    @Test
    public void disableAndReenableCec_volumeControlReturnsToOriginalValue_enabled() {
    public void disableAndReenableCec_volumeControlReturnsToOriginalValue_enabled() {
        int volumeControlEnabled = HdmiControlManager.VOLUME_CONTROL_ENABLED;
        int volumeControlEnabled = HdmiControlManager.VOLUME_CONTROL_ENABLED;
+26 −0
Original line number Original line Diff line number Diff line
@@ -16,11 +16,14 @@


package com.android.server.hdmi;
package com.android.server.hdmi;


import static android.hardware.hdmi.HdmiDeviceInfo.DEVICE_TV;

import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;


import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertThat;


import android.content.Context;
import android.content.Context;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.os.Looper;
import android.os.Looper;
import android.os.test.TestLooper;
import android.os.test.TestLooper;
@@ -35,6 +38,7 @@ import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.junit.runners.JUnit4;


import java.util.Collections;
import java.util.Collections;
import java.util.List;


/**
/**
 * TV specific tests for {@link HdmiControlService} class.
 * TV specific tests for {@link HdmiControlService} class.
@@ -47,6 +51,7 @@ public class HdmiControlServiceTvTest {
    private static final String TAG = "HdmiControlServiceTvTest";
    private static final String TAG = "HdmiControlServiceTvTest";
    private HdmiControlService mHdmiControlService;
    private HdmiControlService mHdmiControlService;
    private HdmiCecController mHdmiCecController;
    private HdmiCecController mHdmiCecController;
    private HdmiCecLocalDeviceTv mHdmiCecLocalDeviceTv;
    private FakeNativeWrapper mNativeWrapper;
    private FakeNativeWrapper mNativeWrapper;
    private HdmiEarcController mHdmiEarcController;
    private HdmiEarcController mHdmiEarcController;
    private FakeEarcNativeWrapper mEarcNativeWrapper;
    private FakeEarcNativeWrapper mEarcNativeWrapper;
@@ -90,6 +95,8 @@ public class HdmiControlServiceTvTest {
        mHdmiControlService.initService();
        mHdmiControlService.initService();


        mTestLooper.dispatchAll();
        mTestLooper.dispatchAll();

        mHdmiCecLocalDeviceTv = mHdmiControlService.tv();
    }
    }


    @Test
    @Test
@@ -139,4 +146,23 @@ public class HdmiControlServiceTvTest {
        assertThat(mHdmiControlService
        assertThat(mHdmiControlService
                .verifyPhysicalAddresses(HdmiUtils.buildMessage("4F:82:10"))).isFalse();
                .verifyPhysicalAddresses(HdmiUtils.buildMessage("4F:82:10"))).isFalse();
    }
    }

    @Test
    public void setRcProfileTv_reportFeatureBroadcast() {
        mNativeWrapper.clearResultMessages();

        mHdmiControlService.getHdmiCecConfig().setIntValue(
                HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
                HdmiControlManager.HDMI_CEC_VERSION_2_0);
        mHdmiControlService.getHdmiCecConfig().setIntValue(
                HdmiControlManager.CEC_SETTING_NAME_RC_PROFILE_TV,
                HdmiControlManager.RC_PROFILE_TV_NONE);
        mTestLooper.dispatchAll();

        HdmiCecMessage reportFeatures = ReportFeaturesMessage.build(Constants.ADDR_TV,
                HdmiControlManager.HDMI_CEC_VERSION_2_0, List.of(DEVICE_TV),
                mHdmiCecLocalDeviceTv.getRcProfile(), mHdmiCecLocalDeviceTv.getRcFeatures(),
                mHdmiCecLocalDeviceTv.getDeviceFeatures());
        assertThat(mNativeWrapper.getResultMessages()).contains(reportFeatures);
    }
}
}