From ea48ccb1ef6b77ff9e40338ebb75bb0abaa1ac68 Mon Sep 17 00:00:00 2001 From: Michal Olech Date: Wed, 13 May 2020 16:45:47 +0200 Subject: [PATCH] [CEC] Standby when lost Add an option to go to standby when received from other device For better configurability, a "ro.hdmi.cec.source.power_state_change_on_active_source_lost" system property is introduced which controls the new behaviour. Bug: 156367087 Test: manually tested on a device Change-Id: I7a068064bb5e867fd364d2b84c7066db06baec3e Merged-In: I7a068064bb5e867fd364d2b84c7066db06baec3e --- .../com/android/server/hdmi/Constants.java | 16 ++++++ .../hdmi/HdmiCecLocalDevicePlayback.java | 30 +++++++++++ .../hdmi/HdmiCecLocalDevicePlaybackTest.java | 52 +++++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index 694f0d6fce405..13b6c7c3ea46a 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -500,6 +500,22 @@ final class Constants { static final String PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_WAKE_UP_AND_SEND_ACTIVE_SOURCE = "wake_up_and_send_active_source"; + /** + * Property to decide the device behaviour when is lost. + * + *

This property applies to playback devices. + *

Possible values are: + *

    + *
  • none No power state change (default). + *
  • standby_now PowerManager.goToSleep() is called. + *
+ */ + static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST = + "ro.hdmi.cec.source.power_state_change_on_active_source_lost"; + + static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE = "none"; + static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW = "standby_now"; + 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 d5168acc90d0c..ef2781082a240 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -67,6 +67,10 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { @VisibleForTesting protected String mPlaybackDeviceActionOnRoutingControl; + // Behaviour of the device when is lost in favor of another device. + @VisibleForTesting + protected String mPowerStateChangeOnActiveSourceLost; + HdmiCecLocalDevicePlayback(HdmiControlService service) { super(service, HdmiDeviceInfo.DEVICE_PLAYBACK); @@ -79,6 +83,10 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { mPlaybackDeviceActionOnRoutingControl = SystemProperties.get( Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL, Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_NONE); + + mPowerStateChangeOnActiveSourceLost = SystemProperties.get( + Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, + Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE); } @Override @@ -240,6 +248,28 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { return !getWakeLock().isHeld(); } + @Override + @ServiceThreadOnly + protected boolean handleActiveSource(HdmiCecMessage message) { + super.handleActiveSource(message); + if (mIsActiveSource) { + return true; + } + switch (mPowerStateChangeOnActiveSourceLost) { + case Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW: + mService.standby(); + return true; + case Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE: + return true; + default: + Slog.w(TAG, "Invalid property '" + + Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST + + "' value: " + + mPowerStateChangeOnActiveSourceLost); + return true; + } + } + @ServiceThreadOnly protected boolean handleUserControlPressed(HdmiCecMessage message) { assertRunOnServiceThread(); 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 48e70e01f4f51..c44f12735fb50 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -57,6 +57,7 @@ public class HdmiCecLocalDevicePlaybackTest { private ArrayList mLocalDevices = new ArrayList<>(); private int mPlaybackPhysicalAddress; private boolean mWokenUp; + private boolean mStandby; @Mock private IPowerManager mIPowerManagerMock; @Mock private IThermalService mIThermalServiceMock; @@ -76,6 +77,11 @@ public class HdmiCecLocalDevicePlaybackTest { mWokenUp = true; } + @Override + void standby() { + mStandby = true; + } + @Override boolean isControlEnabled() { return true; @@ -336,6 +342,52 @@ public class HdmiCecLocalDevicePlaybackTest { assertThat(mNativeWrapper.getResultMessages()).contains(standbyMessage); } + @Test + public void handleActiveSource_ActiveSource_None() { + mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost = + Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE; + mStandby = false; + HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1, + mPlaybackPhysicalAddress); + assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue(); + mTestLooper.dispatchAll(); + assertThat(mStandby).isFalse(); + } + + @Test + public void handleActiveSource_notActiveSource_None() { + mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost = + Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE; + mStandby = false; + HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(ADDR_TV, 0x0000); + assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue(); + mTestLooper.dispatchAll(); + assertThat(mStandby).isFalse(); + } + + @Test + public void handleActiveSource_ActiveSource_StandbyNow() { + mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost = + Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW; + mStandby = false; + HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1, + mPlaybackPhysicalAddress); + assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue(); + mTestLooper.dispatchAll(); + assertThat(mStandby).isFalse(); + } + + @Test + public void handleActiveSource_notActiveSource_StandbyNow() { + mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost = + Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW; + mStandby = false; + HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(ADDR_TV, 0x0000); + assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue(); + mTestLooper.dispatchAll(); + assertThat(mStandby).isTrue(); + } + @Test public void sendVolumeKeyEvent_up_volumeEnabled() { mHdmiControlService.setHdmiCecVolumeControlEnabled(true);