From 0786ebc98e63c8ab2650d9fead025e2e73c9aa21 Mon Sep 17 00:00:00 2001 From: Marvin Ramin Date: Tue, 1 Dec 2020 15:30:11 +0100 Subject: [PATCH] Update handling of incoming CEC power key presses Update handling of messages with power related operands. Power commands change the power status properly and should not be converted to power keycodes. This particularly changes the handling of ["Power"] which could be converted to KEYCODE_POWER before when the device was on when the keycode was received, causing the device to turn off. This is no longer supported and ["Power"] will be treated as a power on command. Test: atest HdmiCecLocalDeviceTest Fixes: 174452275 Change-Id: I10f6d0d235d999bd29b54ba96728c0bda9697ec5 --- .../server/hdmi/HdmiCecLocalDevice.java | 8 ++ .../server/hdmi/HdmiCecLocalDeviceTest.java | 108 ++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 0e196f278ddf9..52121f3527836 100755 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -623,6 +623,14 @@ abstract class HdmiCecLocalDevice { return false; } + if (isPowerOffOrToggleCommand(message) || isPowerOnOrToggleCommand(message)) { + // Power commands should already be handled above. Don't continue and convert the CEC + // keycode to Android keycode. + // Do not as the local device should already be in the correct power + // state. + return true; + } + final long downTime = SystemClock.uptimeMillis(); final byte[] params = message.getParams(); final int keycode = HdmiCecKeycode.cecKeycodeAndParamsToAndroidKey(params); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java index 2cb1113e7325d..ef77f32bb2116 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java @@ -112,6 +112,7 @@ public class HdmiCecLocalDeviceTest { private HdmiCecMessageValidator mMessageValidator; private static byte[] param; private boolean mStandbyMessageReceived; + private boolean mWakeupMessageReceived; private boolean isControlEnabled; private int mPowerStatus; @@ -130,10 +131,22 @@ public class HdmiCecLocalDeviceTest { || mPowerStatus == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON; } + @Override + boolean isPowerStandbyOrTransient() { + return mPowerStatus == HdmiControlManager.POWER_STATUS_STANDBY + || mPowerStatus + == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY; + } + @Override void standby() { mStandbyMessageReceived = true; } + + @Override + void wakeUp() { + mWakeupMessageReceived = true; + } }; mHdmiControlService.setIoLooper(mTestLooper.getLooper()); mHdmiCecController = HdmiCecController.createWithNativeWrapper( @@ -276,4 +289,99 @@ public class HdmiCecLocalDeviceTest { assertThat(result).isTrue(); } + @Test + public void handleUserControlPressed_power_localDeviceInStandby_shouldTurnOn() { + mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isTrue(); + assertThat(mStandbyMessageReceived).isFalse(); + } + + @Test + public void handleUserControlPressed_power_localDeviceOn_shouldNotChangePowerStatus() { + mPowerStatus = HdmiControlManager.POWER_STATUS_ON; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isFalse(); + assertThat(mStandbyMessageReceived).isFalse(); + } + + @Test + public void handleUserControlPressed_powerToggleFunction_localDeviceInStandby_shouldTurnOn() { + mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isTrue(); + assertThat(mStandbyMessageReceived).isFalse(); + } + + @Test + public void handleUserControlPressed_powerToggleFunction_localDeviceOn_shouldTurnOff() { + mPowerStatus = HdmiControlManager.POWER_STATUS_ON; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isFalse(); + assertThat(mStandbyMessageReceived).isTrue(); + } + + @Test + public void handleUserControlPressed_powerOnFunction_localDeviceInStandby_shouldTurnOn() { + mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isTrue(); + assertThat(mStandbyMessageReceived).isFalse(); + } + + @Test + public void handleUserControlPressed_powerOnFunction_localDeviceOn_noPowerStatusChange() { + mPowerStatus = HdmiControlManager.POWER_STATUS_ON; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isFalse(); + assertThat(mStandbyMessageReceived).isFalse(); + } + + @Test + public void handleUserControlPressed_powerOffFunction_localDeviceStandby_noPowerStatusChange() { + mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER_OFF_FUNCTION)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isFalse(); + assertThat(mStandbyMessageReceived).isFalse(); + } + + @Test + public void handleUserControlPressed_powerOffFunction_localDeviceOn_shouldTurnOff() { + mPowerStatus = HdmiControlManager.POWER_STATUS_ON; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER_OFF_FUNCTION)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isFalse(); + assertThat(mStandbyMessageReceived).isTrue(); + } }