diff options
| author | 2020-05-12 14:47:14 +0200 | |
|---|---|---|
| committer | 2020-06-04 17:54:38 +0200 | |
| commit | 4fd720ad1b72240269a9891c0739239620199118 (patch) | |
| tree | c50798a3fbcea4633aae31eee65a588c64424ab5 | |
| parent | 155d909a0811a383bd0f7d301d9cf28c5058cb4b (diff) | |
[CEC] <Active Source> on Routing Control
Wake up the playback device and optionally send <Active Source> on
Routing Control messages
Before the change: No response to <Routing Change> or <Routing
Information>
After the change: Device wakes up (and optionally sends <Active Source>)
after receiving <Routing Change> or <Routing Information> with its
physical address
For better configurability, a "playback_device_action_on_routing_control" system
property is introduced which controls what should be the behaviour of the device.
Bug: 153950818
Test: flashed a playback device and inspected CEC messages
Change-Id: I5ef3d624f5189dac91d3fd0211e16f00e7a6b77b
4 files changed, 195 insertions, 1 deletions
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index ac3a65310d31..694f0d6fce40 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -483,6 +483,23 @@ final class Constants { static final String PROPERTY_STRIP_AUDIO_TV_NO_SYSTEM_AUDIO = "persist.sys.hdmi.property_strip_audio_tv_no_system_audio"; + /** + * Determines playback device action upon receiving routing control messages. + * <ul> + * <li><b>none</b> No action taken. + * <li><b>wake_up_only</b> PowerManager.wakeUp() is called. + * <li><b>wake_up_and_send_active_source</b> Same as above and + * additionally <Active Source> is sent. + * </ul> + */ + static final String PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL = + "ro.hdmi.cec.source.playback_device_action_on_routing_control"; + + static final String PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_NONE = "none"; + static final String PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_WAKE_UP_ONLY = "wake_up_only"; + static final String PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_WAKE_UP_AND_SEND_ACTIVE_SOURCE = + "wake_up_and_send_active_source"; + static final int RECORDING_TYPE_DIGITAL_RF = 1; static final int RECORDING_TYPE_ANALOGUE_RF = 2; static final int RECORDING_TYPE_EXTERNAL_PHYSICAL_ADDRESS = 3; diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 67861c28b37e..6f9ba182a711 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -63,6 +63,10 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { // TODO(amyjojo): adding system constants for input ports to TIF mapping. private int mLocalActivePath = 0; + // Determines what action should be taken upon receiving Routing Control messages. + @VisibleForTesting + protected String mPlaybackDeviceActionOnRoutingControl; + HdmiCecLocalDevicePlayback(HdmiControlService service) { super(service, HdmiDeviceInfo.DEVICE_PLAYBACK); @@ -71,6 +75,10 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { // The option is false by default. Update settings db as well to have the right // initial setting on UI. mService.writeBooleanSetting(Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED, mAutoTvOff); + + mPlaybackDeviceActionOnRoutingControl = SystemProperties.get( + Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL, + Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_NONE); } @Override @@ -334,6 +342,47 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { } @Override + @ServiceThreadOnly + protected boolean handleRoutingChange(HdmiCecMessage message) { + assertRunOnServiceThread(); + int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams(), 2); + handleRoutingChangeAndInformation(physicalAddress, message); + return true; + } + + @Override + @ServiceThreadOnly + protected boolean handleRoutingInformation(HdmiCecMessage message) { + assertRunOnServiceThread(); + int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams()); + handleRoutingChangeAndInformation(physicalAddress, message); + return true; + } + + @Override + protected void handleRoutingChangeAndInformation(int physicalAddress, HdmiCecMessage message) { + if (physicalAddress != mService.getPhysicalAddress()) { + return; // Do nothing. + } + switch (mPlaybackDeviceActionOnRoutingControl) { + case Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_WAKE_UP_AND_SEND_ACTIVE_SOURCE: + setAndBroadcastActiveSource(message, physicalAddress); + break; + case Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_WAKE_UP_ONLY: + mService.wakeUp(); + break; + case Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_NONE: + break; + default: + Slog.w(TAG, "Invalid property '" + + Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL + + "' value: " + + mPlaybackDeviceActionOnRoutingControl); + break; + } + } + + @Override protected int findKeyReceiverAddress() { return Constants.ADDR_TV; } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java index ae008b4bfa7a..5fe0be950974 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java @@ -199,7 +199,8 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice { // do nothing } - // Source device with Switch functionality should implement this method. + // Only source devices that react to routing control messages should implement + // this method (e.g. a TV with built in switch). // TODO(): decide which type will handle the routing when multi device type is supported protected void handleRoutingChangeAndInformation(int physicalAddress, HdmiCecMessage message) { // do nothing diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java index b76211895ab0..f84284924008 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -15,6 +15,7 @@ */ package com.android.server.hdmi; +import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1; import static com.android.server.hdmi.Constants.ADDR_TV; import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC; @@ -109,6 +110,132 @@ public class HdmiCecLocalDevicePlaybackTest { mNativeWrapper.setPhysicalAddress(mPlaybackPhysicalAddress); } + @Test + public void handleRoutingChange_None() { + mHdmiCecLocalDevicePlayback.mPlaybackDeviceActionOnRoutingControl = + Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_NONE; + + mWokenUp = false; + + HdmiCecMessage message = + HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x0000, + mPlaybackPhysicalAddress); + + HdmiCecMessage expectedMessage = + HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1, + mPlaybackPhysicalAddress); + + assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue(); + mTestLooper.dispatchAll(); + assertThat(mWokenUp).isFalse(); + assertThat(mNativeWrapper.getResultMessages().contains(expectedMessage)).isFalse(); + } + + @Test + public void handleRoutingInformation_None() { + mHdmiCecLocalDevicePlayback.mPlaybackDeviceActionOnRoutingControl = + Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_NONE; + + mWokenUp = false; + + HdmiCecMessage message = + HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, + mPlaybackPhysicalAddress); + + HdmiCecMessage expectedMessage = + HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1, + mPlaybackPhysicalAddress); + + assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue(); + mTestLooper.dispatchAll(); + assertThat(mWokenUp).isFalse(); + assertThat(mNativeWrapper.getResultMessages().contains(expectedMessage)).isFalse(); + } + + @Test + public void handleRoutingChange_WakeUpOnly() { + mHdmiCecLocalDevicePlayback.mPlaybackDeviceActionOnRoutingControl = + Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_WAKE_UP_ONLY; + + mWokenUp = false; + + HdmiCecMessage message = + HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x0000, + mPlaybackPhysicalAddress); + + HdmiCecMessage expectedMessage = + HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1, + mPlaybackPhysicalAddress); + + assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue(); + mTestLooper.dispatchAll(); + assertThat(mWokenUp).isTrue(); + assertThat(mNativeWrapper.getResultMessages().contains(expectedMessage)).isFalse(); + } + + @Test + public void handleRoutingInformation_WakeUpOnly() { + mHdmiCecLocalDevicePlayback.mPlaybackDeviceActionOnRoutingControl = + Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_WAKE_UP_ONLY; + + mWokenUp = false; + + HdmiCecMessage message = + HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, + mPlaybackPhysicalAddress); + + HdmiCecMessage expectedMessage = + HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1, + mPlaybackPhysicalAddress); + + assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue(); + mTestLooper.dispatchAll(); + assertThat(mWokenUp).isTrue(); + assertThat(mNativeWrapper.getResultMessages().contains(expectedMessage)).isFalse(); + } + + @Test + public void handleRoutingChange_WakeUpAndSendActiveSource() { + mHdmiCecLocalDevicePlayback.mPlaybackDeviceActionOnRoutingControl = + Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_WAKE_UP_AND_SEND_ACTIVE_SOURCE; + + mWokenUp = false; + + HdmiCecMessage message = + HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x0000, + mPlaybackPhysicalAddress); + + HdmiCecMessage expectedMessage = + HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1, + mPlaybackPhysicalAddress); + + assertThat(mHdmiCecLocalDevicePlayback.handleRoutingChange(message)).isTrue(); + mTestLooper.dispatchAll(); + assertThat(mWokenUp).isTrue(); + assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); + } + + @Test + public void handleRoutingInformation_WakeUpAndSendActiveSource() { + mHdmiCecLocalDevicePlayback.mPlaybackDeviceActionOnRoutingControl = + Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_WAKE_UP_AND_SEND_ACTIVE_SOURCE; + + mWokenUp = false; + + HdmiCecMessage message = + HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, + mPlaybackPhysicalAddress); + + HdmiCecMessage expectedMessage = + HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1, + mPlaybackPhysicalAddress); + + assertThat(mHdmiCecLocalDevicePlayback.handleRoutingInformation(message)).isTrue(); + mTestLooper.dispatchAll(); + assertThat(mWokenUp).isTrue(); + assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage); + } + // Playback device does not handle routing control related feature right now @Ignore("b/120845532") @Test |