From e96fe8f40d975faf969a3fed46a7133da1da841a Mon Sep 17 00:00:00 2001 From: Paul Date: Wed, 15 Sep 2021 15:45:35 +0000 Subject: [PATCH] HDMICEC: Add a new validation to CEC messages Add one more parameter to the isValid() method to indicate if the message that needs to be validated is sent or received by the device. Add a filter that ignores received messages which have source's logical address equal to device's logical address. Revise isValid() calls and tests affected by the change. Edit HdmiControlServiceTest#handleCecCommand_errorParameter_returnsAbortInvalidOperand() test. Since the logical address Constants.ADDR_PLAYBACK_1 is already used by mPlaybackDeviceSpy the message's source is set to Constants.ADDR_PLAYBACK_2; otherwise HdmiCecMessageValidator#isValid() fails with a different error code than expected. Bug: 198261021 Test: make && atest CtsHdmiCecHostTestCases Change-Id: I274a9a2385d616784dfc891aabd8f335c32658da (cherry picked from commit c3d3e32e50fe162f40d69f9f204468a30ea3e201) --- .../server/hdmi/HdmiCecMessageValidator.java | 18 +++++++++++++++++- .../server/hdmi/HdmiControlService.java | 8 ++++---- .../server/hdmi/HdmiCecLocalDeviceTest.java | 2 +- .../hdmi/HdmiCecMessageValidatorTest.java | 2 +- .../server/hdmi/HdmiControlServiceTest.java | 2 +- 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java index 5802e53c67f1c..8a727c6ffb24d 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java @@ -254,7 +254,7 @@ public class HdmiCecMessageValidator { mValidationInfo.append(opcode, new ValidationInfo(validator, addrType)); } - int isValid(HdmiCecMessage message) { + int isValid(HdmiCecMessage message, boolean isMessageReceived) { int opcode = message.getOpcode(); ValidationInfo info = mValidationInfo.get(opcode); if (info == null) { @@ -268,6 +268,22 @@ public class HdmiCecMessageValidator { HdmiLogger.warning("Unexpected source: " + message); return ERROR_SOURCE; } + + if (isMessageReceived) { + // Check if the source's logical address and local device's logical + // address are the same. + for (HdmiCecLocalDevice device : mService.getAllLocalDevices()) { + synchronized (device.mLock) { + if (message.getSource() == device.getDeviceInfo().getLogicalAddress() + && message.getSource() != Constants.ADDR_UNREGISTERED) { + HdmiLogger.warning( + "Unexpected source: message sent from device itself, " + message); + return ERROR_SOURCE; + } + } + } + } + // Check the destination field. if (message.getDestination() == Constants.ADDR_BROADCAST) { if ((info.addressType & DEST_BROADCAST) == 0) { diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index a086bdaa6ec9f..fac8cfe4ab867 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -1132,7 +1132,7 @@ public class HdmiControlService extends SystemService { @ServiceThreadOnly void sendCecCommand(HdmiCecMessage command, @Nullable SendMessageCallback callback) { assertRunOnServiceThread(); - if (mMessageValidator.isValid(command) == HdmiCecMessageValidator.OK) { + if (mMessageValidator.isValid(command, false) == HdmiCecMessageValidator.OK) { mCecController.sendCommand(command, callback); } else { HdmiLogger.error("Invalid message type:" + command); @@ -1165,7 +1165,7 @@ public class HdmiControlService extends SystemService { @Constants.HandleMessageResult protected int handleCecCommand(HdmiCecMessage message) { assertRunOnServiceThread(); - int errorCode = mMessageValidator.isValid(message); + int errorCode = mMessageValidator.isValid(message, true); if (errorCode != HdmiCecMessageValidator.OK) { // We'll not response on the messages with the invalid source or destination // or with parameter length shorter than specified in the standard. @@ -3549,8 +3549,8 @@ public class HdmiControlService extends SystemService { invokeInputChangeListener(info); } - void setMhlInputChangeEnabled(boolean enabled) { - mMhlController.setOption(OPTION_MHL_INPUT_SWITCHING, toInt(enabled)); + void setMhlInputChangeEnabled(boolean enabled) { + mMhlController.setOption(OPTION_MHL_INPUT_SWITCHING, toInt(enabled)); synchronized (mLock) { mMhlInputChangeEnabled = enabled; 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 4673d8dafd1f7..4426f00fba20b 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java @@ -191,7 +191,7 @@ public class HdmiCecLocalDeviceTest { mMessageValidator = new HdmiCecMessageValidator(mHdmiControlService) { @Override - int isValid(HdmiCecMessage message) { + int isValid(HdmiCecMessage message, boolean isMessageReceived) { return HdmiCecMessageValidator.OK; } }; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java index 2307a85fe9cd2..3de7969eef50e 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java @@ -647,6 +647,6 @@ public class HdmiCecMessageValidatorTest { } private IntegerSubject assertMessageValidity(String message) { - return assertThat(mHdmiCecMessageValidator.isValid(HdmiUtils.buildMessage(message))); + return assertThat(mHdmiCecMessageValidator.isValid(HdmiUtils.buildMessage(message), false)); } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java index f53ae525eabab..d03b67480b725 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java @@ -793,7 +793,7 @@ public class HdmiControlServiceTest { @Test public void handleCecCommand_errorParameter_returnsAbortInvalidOperand() { // Validity ERROR_PARAMETER. Taken from HdmiCecMessageValidatorTest#isValid_menuStatus - HdmiCecMessage message = HdmiUtils.buildMessage("40:8D:03"); + HdmiCecMessage message = HdmiUtils.buildMessage("80:8D:03"); assertThat(mHdmiControlServiceSpy.handleCecCommand(message)) .isEqualTo(Constants.ABORT_INVALID_OPERAND);