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

Commit d46f59b3 authored by Alison Chang's avatar Alison Chang
Browse files

Feature abort when receiving the wrong format message of <System Audio Mode Status>

TCL issue 1-1. (different solution)
Some soundbars respond to <System Audio Mode Status> with wrong format, and that will make it fail to connect.
To fix this, check <System Audio Mode Status> message format before handling it; if it's wrong, send feature abort with reason "Invalid Operand".

Bug: 244529779
Bug: 230663730
Test: Unit tests
Change-Id: I3d2e008f8e5f9ac3956d3de5382b95f1aeca7a9e
parent 6c31e645
Loading
Loading
Loading
Loading
+41 −12
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ public class HdmiCecMessageValidator {
            ERROR_DESTINATION,
            ERROR_PARAMETER,
            ERROR_PARAMETER_SHORT,
            ERROR_PARAMETER_LONG,
    })
    public @interface ValidationResult {};

@@ -43,6 +44,7 @@ public class HdmiCecMessageValidator {
    static final int ERROR_DESTINATION = 2;
    static final int ERROR_PARAMETER = 3;
    static final int ERROR_PARAMETER_SHORT = 4;
    static final int ERROR_PARAMETER_LONG = 5;

    interface ParameterValidator {
        /**
@@ -159,11 +161,13 @@ public class HdmiCecMessageValidator {
        addValidationInfo(Constants.MESSAGE_SET_MENU_LANGUAGE,
                new AsciiValidator(3), DEST_BROADCAST);

        ParameterValidator statusRequestValidator = new OneByteRangeValidator(0x01, 0x03);
        ParameterValidator statusRequestValidator = new MinimumOneByteRangeValidator(0x01, 0x03);
        addValidationInfo(
                Constants.MESSAGE_DECK_CONTROL, new OneByteRangeValidator(0x01, 0x04), DEST_DIRECT);
                Constants.MESSAGE_DECK_CONTROL,
                        new MinimumOneByteRangeValidator(0x01, 0x04), DEST_DIRECT);
        addValidationInfo(
                Constants.MESSAGE_DECK_STATUS, new OneByteRangeValidator(0x11, 0x1F), DEST_DIRECT);
                Constants.MESSAGE_DECK_STATUS,
                        new MinimumOneByteRangeValidator(0x11, 0x1F), DEST_DIRECT);
        addValidationInfo(Constants.MESSAGE_GIVE_DECK_STATUS, statusRequestValidator, DEST_DIRECT);
        addValidationInfo(Constants.MESSAGE_PLAY, new PlayModeValidator(), DEST_DIRECT);

@@ -201,9 +205,11 @@ public class HdmiCecMessageValidator {

        // Messages for the Device Menu Control.
        addValidationInfo(
                Constants.MESSAGE_MENU_REQUEST, new OneByteRangeValidator(0x00, 0x02), DEST_DIRECT);
                Constants.MESSAGE_MENU_REQUEST,
                        new MinimumOneByteRangeValidator(0x00, 0x02), DEST_DIRECT);
        addValidationInfo(
                Constants.MESSAGE_MENU_STATUS, new OneByteRangeValidator(0x00, 0x01), DEST_DIRECT);
                Constants.MESSAGE_MENU_STATUS,
                        new MinimumOneByteRangeValidator(0x00, 0x01), DEST_DIRECT);

        // Messages for the Remote Control Passthrough.
        addValidationInfo(
@@ -214,7 +220,7 @@ public class HdmiCecMessageValidator {
        // Messages for the Power Status.
        addValidationInfo(
                Constants.MESSAGE_REPORT_POWER_STATUS,
                new OneByteRangeValidator(0x00, 0x03),
                new MinimumOneByteRangeValidator(0x00, 0x03),
                DEST_DIRECT | DEST_BROADCAST);

        // Messages for the General Protocol.
@@ -229,17 +235,17 @@ public class HdmiCecMessageValidator {
                oneByteValidator, DEST_DIRECT);
        addValidationInfo(
                Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE,
                new OneByteRangeValidator(0x00, 0x01),
                new MinimumOneByteRangeValidator(0x00, 0x01),
                DEST_ALL);
        addValidationInfo(
                Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS,
                new OneByteRangeValidator(0x00, 0x01),
                new SingleByteRangeValidator(0x00, 0x01),
                DEST_DIRECT);

        // Messages for the Audio Rate Control.
        addValidationInfo(
                Constants.MESSAGE_SET_AUDIO_RATE,
                new OneByteRangeValidator(0x00, 0x06),
                new MinimumOneByteRangeValidator(0x00, 0x06),
                DEST_DIRECT);

        // Messages for Feature Discovery.
@@ -900,11 +906,32 @@ public class HdmiCecMessageValidator {
        }
    }

    /** Check if the given parameters are one byte parameters and within range. */
    private static class OneByteRangeValidator implements ParameterValidator {
    /**
     * Check if the given parameters are at least one byte parameters
     * and the first byte is within range.
     */
    private static class MinimumOneByteRangeValidator implements ParameterValidator {
        private final int mMinValue, mMaxValue;

        MinimumOneByteRangeValidator(int minValue, int maxValue) {
            mMinValue = minValue;
            mMaxValue = maxValue;
        }

        @Override
        public int isValid(byte[] params) {
            if (params.length < 1) {
                return ERROR_PARAMETER_SHORT;
            }
            return toErrorCode(isWithinRange(params[0], mMinValue, mMaxValue));
        }
    }

    /** Check if the given parameters are exactly one byte parameters and within range. */
    private static class SingleByteRangeValidator implements ParameterValidator {
        private final int mMinValue, mMaxValue;

        OneByteRangeValidator(int minValue, int maxValue) {
        SingleByteRangeValidator(int minValue, int maxValue) {
            mMinValue = minValue;
            mMaxValue = maxValue;
        }
@@ -913,6 +940,8 @@ public class HdmiCecMessageValidator {
        public int isValid(byte[] params) {
            if (params.length < 1) {
                return ERROR_PARAMETER_SHORT;
            } else if (params.length > 1) {
                return ERROR_PARAMETER_LONG;
            }
            return toErrorCode(isWithinRange(params[0], mMinValue, mMaxValue));
        }
+1 −0
Original line number Diff line number Diff line
@@ -1609,6 +1609,7 @@ public class HdmiControlService extends SystemService {
        @HdmiCecMessageValidator.ValidationResult
        int validationResult = message.getValidationResult();
        if (validationResult == HdmiCecMessageValidator.ERROR_PARAMETER
                || validationResult == HdmiCecMessageValidator.ERROR_PARAMETER_LONG
                || !verifyPhysicalAddresses(message)) {
            return Constants.ABORT_INVALID_OPERAND;
        } else if (validationResult != HdmiCecMessageValidator.OK
+3 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.hdmi;

import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_DESTINATION;
import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER;
import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER_LONG;
import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER_SHORT;
import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_SOURCE;
import static com.android.server.hdmi.HdmiCecMessageValidator.OK;
@@ -145,11 +146,12 @@ public class HdmiCecMessageValidatorTest {
    @Test
    public void isValid_systemAudioModeStatus() {
        assertMessageValidity("40:7E:00").isEqualTo(OK);
        assertMessageValidity("40:7E:01:01").isEqualTo(OK);
        assertMessageValidity("40:7E:01").isEqualTo(OK);

        assertMessageValidity("0F:7E:00").isEqualTo(ERROR_DESTINATION);
        assertMessageValidity("F0:7E").isEqualTo(ERROR_SOURCE);
        assertMessageValidity("40:7E").isEqualTo(ERROR_PARAMETER_SHORT);
        assertMessageValidity("40:7E:01:1F:28").isEqualTo(ERROR_PARAMETER_LONG);
        assertMessageValidity("40:7E:02").isEqualTo(ERROR_PARAMETER);
    }

+7 −0
Original line number Diff line number Diff line
@@ -761,6 +761,13 @@ public class HdmiControlServiceTest {

        assertThat(mHdmiControlServiceSpy.handleCecCommand(message))
                .isEqualTo(Constants.ABORT_INVALID_OPERAND);

        // Validating ERROR_PARAMETER_LONG will generate ABORT_INVALID_OPERAND.
        // Taken from HdmiCecMessageValidatorTest#isValid_systemAudioModeStatus
        HdmiCecMessage systemAudioModeStatus = HdmiUtils.buildMessage("40:7E:01:1F:28");

        assertThat(mHdmiControlServiceSpy.handleCecCommand(systemAudioModeStatus))
                .isEqualTo(Constants.ABORT_INVALID_OPERAND);
    }

    @Test