1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.hdmi; 18 19 import android.annotation.IntDef; 20 import android.hardware.hdmi.HdmiDeviceInfo; 21 import android.util.SparseArray; 22 23 /** 24 * A helper class to validate {@link HdmiCecMessage}. 25 * 26 * If a message type has its own specific subclass of {@link HdmiCecMessage}, 27 * validation is performed in that subclass instead. 28 */ 29 public class HdmiCecMessageValidator { 30 private static final String TAG = "HdmiCecMessageValidator"; 31 32 @IntDef({ 33 OK, 34 ERROR_SOURCE, 35 ERROR_DESTINATION, 36 ERROR_PARAMETER, 37 ERROR_PARAMETER_SHORT, 38 }) 39 public @interface ValidationResult {}; 40 41 static final int OK = 0; 42 static final int ERROR_SOURCE = 1; 43 static final int ERROR_DESTINATION = 2; 44 static final int ERROR_PARAMETER = 3; 45 static final int ERROR_PARAMETER_SHORT = 4; 46 47 interface ParameterValidator { 48 /** 49 * @return errorCode errorCode can be {@link #OK}, {@link #ERROR_PARAMETER} or 50 * {@link #ERROR_PARAMETER_SHORT}. 51 */ isValid(byte[] params)52 int isValid(byte[] params); 53 } 54 55 // Only the direct addressing is allowed. 56 public static final int DEST_DIRECT = 1 << 0; 57 // Only the broadcast addressing is allowed. 58 public static final int DEST_BROADCAST = 1 << 1; 59 // Both the direct and the broadcast addressing are allowed. 60 public static final int DEST_ALL = DEST_DIRECT | DEST_BROADCAST; 61 // True if the messages from address 15 (unregistered) are allowed. 62 public static final int SRC_UNREGISTERED = 1 << 2; 63 64 private static class ValidationInfo { 65 public final ParameterValidator parameterValidator; 66 public final int addressType; 67 ValidationInfo(ParameterValidator validator, int type)68 public ValidationInfo(ParameterValidator validator, int type) { 69 parameterValidator = validator; 70 addressType = type; 71 } 72 } 73 HdmiCecMessageValidator()74 private HdmiCecMessageValidator() {} 75 76 private static final SparseArray<ValidationInfo> sValidationInfo = new SparseArray<>(); 77 78 static { 79 // Messages related to the physical address. 80 PhysicalAddressValidator physicalAddressValidator = new PhysicalAddressValidator(); addValidationInfo(Constants.MESSAGE_ACTIVE_SOURCE, physicalAddressValidator, DEST_BROADCAST | SRC_UNREGISTERED)81 addValidationInfo(Constants.MESSAGE_ACTIVE_SOURCE, 82 physicalAddressValidator, DEST_BROADCAST | SRC_UNREGISTERED); addValidationInfo(Constants.MESSAGE_INACTIVE_SOURCE, physicalAddressValidator, DEST_DIRECT)83 addValidationInfo(Constants.MESSAGE_INACTIVE_SOURCE, physicalAddressValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS, new ReportPhysicalAddressValidator(), DEST_BROADCAST | SRC_UNREGISTERED)84 addValidationInfo(Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS, 85 new ReportPhysicalAddressValidator(), DEST_BROADCAST | SRC_UNREGISTERED); addValidationInfo(Constants.MESSAGE_ROUTING_CHANGE, new RoutingChangeValidator(), DEST_BROADCAST | SRC_UNREGISTERED)86 addValidationInfo(Constants.MESSAGE_ROUTING_CHANGE, 87 new RoutingChangeValidator(), DEST_BROADCAST | SRC_UNREGISTERED); addValidationInfo(Constants.MESSAGE_ROUTING_INFORMATION, physicalAddressValidator, DEST_BROADCAST | SRC_UNREGISTERED)88 addValidationInfo(Constants.MESSAGE_ROUTING_INFORMATION, 89 physicalAddressValidator, DEST_BROADCAST | SRC_UNREGISTERED); addValidationInfo(Constants.MESSAGE_SET_STREAM_PATH, physicalAddressValidator, DEST_BROADCAST)90 addValidationInfo(Constants.MESSAGE_SET_STREAM_PATH, 91 physicalAddressValidator, DEST_BROADCAST); addValidationInfo(Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST, new SystemAudioModeRequestValidator(), DEST_DIRECT)92 addValidationInfo(Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST, 93 new SystemAudioModeRequestValidator(), DEST_DIRECT); 94 95 // Messages have no parameter. 96 FixedLengthValidator noneValidator = new FixedLengthValidator(0); addValidationInfo(Constants.MESSAGE_ABORT, noneValidator, DEST_DIRECT)97 addValidationInfo(Constants.MESSAGE_ABORT, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_GET_CEC_VERSION, noneValidator, DEST_DIRECT)98 addValidationInfo(Constants.MESSAGE_GET_CEC_VERSION, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_GET_MENU_LANGUAGE, noneValidator, DEST_DIRECT | SRC_UNREGISTERED)99 addValidationInfo(Constants.MESSAGE_GET_MENU_LANGUAGE, 100 noneValidator, DEST_DIRECT | SRC_UNREGISTERED); addValidationInfo(Constants.MESSAGE_GIVE_AUDIO_STATUS, noneValidator, DEST_DIRECT)101 addValidationInfo(Constants.MESSAGE_GIVE_AUDIO_STATUS, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS, noneValidator, DEST_DIRECT)102 addValidationInfo(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID, noneValidator, DEST_DIRECT | SRC_UNREGISTERED)103 addValidationInfo(Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID, 104 noneValidator, DEST_DIRECT | SRC_UNREGISTERED); addValidationInfo(Constants.MESSAGE_GIVE_OSD_NAME, noneValidator, DEST_DIRECT)105 addValidationInfo(Constants.MESSAGE_GIVE_OSD_NAME, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS, noneValidator, DEST_DIRECT | SRC_UNREGISTERED)106 addValidationInfo(Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS, 107 noneValidator, DEST_DIRECT | SRC_UNREGISTERED); addValidationInfo(Constants.MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS, noneValidator, DEST_DIRECT)108 addValidationInfo(Constants.MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS, 109 noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_IMAGE_VIEW_ON, noneValidator, DEST_DIRECT)110 addValidationInfo(Constants.MESSAGE_IMAGE_VIEW_ON, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_INITIATE_ARC, noneValidator, DEST_DIRECT)111 addValidationInfo(Constants.MESSAGE_INITIATE_ARC, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_RECORD_OFF, noneValidator, DEST_DIRECT)112 addValidationInfo(Constants.MESSAGE_RECORD_OFF, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_RECORD_TV_SCREEN, noneValidator, DEST_DIRECT)113 addValidationInfo(Constants.MESSAGE_RECORD_TV_SCREEN, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_REPORT_ARC_INITIATED, noneValidator, DEST_DIRECT)114 addValidationInfo(Constants.MESSAGE_REPORT_ARC_INITIATED, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_REPORT_ARC_TERMINATED, noneValidator, DEST_DIRECT)115 addValidationInfo(Constants.MESSAGE_REPORT_ARC_TERMINATED, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_REQUEST_ARC_INITIATION, noneValidator, DEST_DIRECT)116 addValidationInfo(Constants.MESSAGE_REQUEST_ARC_INITIATION, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_REQUEST_ARC_TERMINATION, noneValidator, DEST_DIRECT)117 addValidationInfo(Constants.MESSAGE_REQUEST_ARC_TERMINATION, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_REQUEST_ACTIVE_SOURCE, noneValidator, DEST_BROADCAST | SRC_UNREGISTERED)118 addValidationInfo(Constants.MESSAGE_REQUEST_ACTIVE_SOURCE, 119 noneValidator, DEST_BROADCAST | SRC_UNREGISTERED); addValidationInfo(Constants.MESSAGE_STANDBY, noneValidator, DEST_ALL | SRC_UNREGISTERED)120 addValidationInfo(Constants.MESSAGE_STANDBY, noneValidator, DEST_ALL | SRC_UNREGISTERED); addValidationInfo(Constants.MESSAGE_TERMINATE_ARC, noneValidator, DEST_DIRECT)121 addValidationInfo(Constants.MESSAGE_TERMINATE_ARC, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_TEXT_VIEW_ON, noneValidator, DEST_DIRECT)122 addValidationInfo(Constants.MESSAGE_TEXT_VIEW_ON, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_TUNER_STEP_DECREMENT, noneValidator, DEST_DIRECT)123 addValidationInfo(Constants.MESSAGE_TUNER_STEP_DECREMENT, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_TUNER_STEP_INCREMENT, noneValidator, DEST_DIRECT)124 addValidationInfo(Constants.MESSAGE_TUNER_STEP_INCREMENT, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_USER_CONTROL_RELEASED, noneValidator, DEST_DIRECT)125 addValidationInfo(Constants.MESSAGE_USER_CONTROL_RELEASED, noneValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_VENDOR_REMOTE_BUTTON_UP, noneValidator, DEST_ALL)126 addValidationInfo(Constants.MESSAGE_VENDOR_REMOTE_BUTTON_UP, noneValidator, DEST_ALL); 127 128 // TODO: Validate more than length for the following messages. 129 130 // Messages for the One Touch Record. addValidationInfo(Constants.MESSAGE_RECORD_ON, new VariableLengthValidator(1, 8), DEST_DIRECT)131 addValidationInfo(Constants.MESSAGE_RECORD_ON, 132 new VariableLengthValidator(1, 8), DEST_DIRECT); addValidationInfo(Constants.MESSAGE_RECORD_STATUS, new RecordStatusInfoValidator(), DEST_DIRECT)133 addValidationInfo(Constants.MESSAGE_RECORD_STATUS, 134 new RecordStatusInfoValidator(), DEST_DIRECT); 135 addValidationInfo( Constants.MESSAGE_CLEAR_ANALOG_TIMER, new AnalogueTimerValidator(), DEST_DIRECT)136 addValidationInfo( 137 Constants.MESSAGE_CLEAR_ANALOG_TIMER, new AnalogueTimerValidator(), DEST_DIRECT); addValidationInfo( Constants.MESSAGE_CLEAR_DIGITAL_TIMER, new DigitalTimerValidator(), DEST_DIRECT)138 addValidationInfo( 139 Constants.MESSAGE_CLEAR_DIGITAL_TIMER, new DigitalTimerValidator(), DEST_DIRECT); addValidationInfo( Constants.MESSAGE_CLEAR_EXTERNAL_TIMER, new ExternalTimerValidator(), DEST_DIRECT)140 addValidationInfo( 141 Constants.MESSAGE_CLEAR_EXTERNAL_TIMER, new ExternalTimerValidator(), DEST_DIRECT); addValidationInfo( Constants.MESSAGE_SET_ANALOG_TIMER, new AnalogueTimerValidator(), DEST_DIRECT)142 addValidationInfo( 143 Constants.MESSAGE_SET_ANALOG_TIMER, new AnalogueTimerValidator(), DEST_DIRECT); addValidationInfo( Constants.MESSAGE_SET_DIGITAL_TIMER, new DigitalTimerValidator(), DEST_DIRECT)144 addValidationInfo( 145 Constants.MESSAGE_SET_DIGITAL_TIMER, new DigitalTimerValidator(), DEST_DIRECT); addValidationInfo( Constants.MESSAGE_SET_EXTERNAL_TIMER, new ExternalTimerValidator(), DEST_DIRECT)146 addValidationInfo( 147 Constants.MESSAGE_SET_EXTERNAL_TIMER, new ExternalTimerValidator(), DEST_DIRECT); addValidationInfo( Constants.MESSAGE_SET_TIMER_PROGRAM_TITLE, new AsciiValidator(1, 14), DEST_DIRECT)148 addValidationInfo( 149 Constants.MESSAGE_SET_TIMER_PROGRAM_TITLE, new AsciiValidator(1, 14), DEST_DIRECT); addValidationInfo( Constants.MESSAGE_TIMER_CLEARED_STATUS, new TimerClearedStatusValidator(), DEST_DIRECT)150 addValidationInfo( 151 Constants.MESSAGE_TIMER_CLEARED_STATUS, 152 new TimerClearedStatusValidator(), 153 DEST_DIRECT); addValidationInfo(Constants.MESSAGE_TIMER_STATUS, new TimerStatusValidator(), DEST_DIRECT)154 addValidationInfo(Constants.MESSAGE_TIMER_STATUS, new TimerStatusValidator(), DEST_DIRECT); 155 156 // Messages for the System Information. 157 FixedLengthValidator oneByteValidator = new FixedLengthValidator(1); addValidationInfo(Constants.MESSAGE_CEC_VERSION, oneByteValidator, DEST_DIRECT)158 addValidationInfo(Constants.MESSAGE_CEC_VERSION, oneByteValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_SET_MENU_LANGUAGE, new AsciiValidator(3), DEST_BROADCAST)159 addValidationInfo(Constants.MESSAGE_SET_MENU_LANGUAGE, 160 new AsciiValidator(3), DEST_BROADCAST); 161 162 ParameterValidator statusRequestValidator = new OneByteRangeValidator(0x01, 0x03); addValidationInfo( Constants.MESSAGE_DECK_CONTROL, new OneByteRangeValidator(0x01, 0x04), DEST_DIRECT)163 addValidationInfo( 164 Constants.MESSAGE_DECK_CONTROL, new OneByteRangeValidator(0x01, 0x04), DEST_DIRECT); addValidationInfo( Constants.MESSAGE_DECK_STATUS, new OneByteRangeValidator(0x11, 0x1F), DEST_DIRECT)165 addValidationInfo( 166 Constants.MESSAGE_DECK_STATUS, new OneByteRangeValidator(0x11, 0x1F), DEST_DIRECT); addValidationInfo(Constants.MESSAGE_GIVE_DECK_STATUS, statusRequestValidator, DEST_DIRECT)167 addValidationInfo(Constants.MESSAGE_GIVE_DECK_STATUS, statusRequestValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_PLAY, new PlayModeValidator(), DEST_DIRECT)168 addValidationInfo(Constants.MESSAGE_PLAY, new PlayModeValidator(), DEST_DIRECT); 169 addValidationInfo( Constants.MESSAGE_GIVE_TUNER_DEVICE_STATUS, statusRequestValidator, DEST_DIRECT)170 addValidationInfo( 171 Constants.MESSAGE_GIVE_TUNER_DEVICE_STATUS, statusRequestValidator, DEST_DIRECT); addValidationInfo( Constants.MESSAGE_SELECT_ANALOG_SERVICE, new SelectAnalogueServiceValidator(), DEST_DIRECT)172 addValidationInfo( 173 Constants.MESSAGE_SELECT_ANALOG_SERVICE, 174 new SelectAnalogueServiceValidator(), 175 DEST_DIRECT); addValidationInfo( Constants.MESSAGE_SELECT_DIGITAL_SERVICE, new SelectDigitalServiceValidator(), DEST_DIRECT)176 addValidationInfo( 177 Constants.MESSAGE_SELECT_DIGITAL_SERVICE, 178 new SelectDigitalServiceValidator(), 179 DEST_DIRECT); addValidationInfo( Constants.MESSAGE_TUNER_DEVICE_STATUS, new TunerDeviceStatusValidator(), DEST_DIRECT)180 addValidationInfo( 181 Constants.MESSAGE_TUNER_DEVICE_STATUS, 182 new TunerDeviceStatusValidator(), 183 DEST_DIRECT); 184 185 // Messages for the Vendor Specific Commands. 186 VariableLengthValidator maxLengthValidator = new VariableLengthValidator(0, 14); addValidationInfo(Constants.MESSAGE_DEVICE_VENDOR_ID, new FixedLengthValidator(3), DEST_BROADCAST)187 addValidationInfo(Constants.MESSAGE_DEVICE_VENDOR_ID, 188 new FixedLengthValidator(3), DEST_BROADCAST); 189 // Allow unregistered source for all vendor specific commands, because we don't know 190 // how to use the commands at this moment. addValidationInfo(Constants.MESSAGE_VENDOR_COMMAND, new VariableLengthValidator(1, 14), DEST_DIRECT | SRC_UNREGISTERED)191 addValidationInfo(Constants.MESSAGE_VENDOR_COMMAND, 192 new VariableLengthValidator(1, 14), DEST_DIRECT | SRC_UNREGISTERED); addValidationInfo(Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, new VariableLengthValidator(4, 14), DEST_ALL | SRC_UNREGISTERED)193 addValidationInfo(Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, 194 new VariableLengthValidator(4, 14), DEST_ALL | SRC_UNREGISTERED); addValidationInfo(Constants.MESSAGE_VENDOR_REMOTE_BUTTON_DOWN, maxLengthValidator, DEST_ALL | SRC_UNREGISTERED)195 addValidationInfo(Constants.MESSAGE_VENDOR_REMOTE_BUTTON_DOWN, 196 maxLengthValidator, DEST_ALL | SRC_UNREGISTERED); 197 198 // Messages for the OSD. addValidationInfo(Constants.MESSAGE_SET_OSD_STRING, new OsdStringValidator(), DEST_DIRECT)199 addValidationInfo(Constants.MESSAGE_SET_OSD_STRING, new OsdStringValidator(), DEST_DIRECT); addValidationInfo(Constants.MESSAGE_SET_OSD_NAME, new AsciiValidator(1, 14), DEST_DIRECT)200 addValidationInfo(Constants.MESSAGE_SET_OSD_NAME, new AsciiValidator(1, 14), DEST_DIRECT); 201 202 // Messages for the Device Menu Control. addValidationInfo( Constants.MESSAGE_MENU_REQUEST, new OneByteRangeValidator(0x00, 0x02), DEST_DIRECT)203 addValidationInfo( 204 Constants.MESSAGE_MENU_REQUEST, new OneByteRangeValidator(0x00, 0x02), DEST_DIRECT); addValidationInfo( Constants.MESSAGE_MENU_STATUS, new OneByteRangeValidator(0x00, 0x01), DEST_DIRECT)205 addValidationInfo( 206 Constants.MESSAGE_MENU_STATUS, new OneByteRangeValidator(0x00, 0x01), DEST_DIRECT); 207 208 // Messages for the Remote Control Passthrough. addValidationInfo( Constants.MESSAGE_USER_CONTROL_PRESSED, new UserControlPressedValidator(), DEST_DIRECT)209 addValidationInfo( 210 Constants.MESSAGE_USER_CONTROL_PRESSED, 211 new UserControlPressedValidator(), 212 DEST_DIRECT); 213 214 // Messages for the Power Status. addValidationInfo( Constants.MESSAGE_REPORT_POWER_STATUS, new OneByteRangeValidator(0x00, 0x03), DEST_DIRECT | DEST_BROADCAST)215 addValidationInfo( 216 Constants.MESSAGE_REPORT_POWER_STATUS, 217 new OneByteRangeValidator(0x00, 0x03), 218 DEST_DIRECT | DEST_BROADCAST); 219 220 // Messages for the General Protocol. addValidationInfo(Constants.MESSAGE_FEATURE_ABORT, new FixedLengthValidator(2), DEST_DIRECT)221 addValidationInfo(Constants.MESSAGE_FEATURE_ABORT, 222 new FixedLengthValidator(2), DEST_DIRECT); 223 224 // Messages for the System Audio Control. addValidationInfo(Constants.MESSAGE_REPORT_AUDIO_STATUS, oneByteValidator, DEST_DIRECT)225 addValidationInfo(Constants.MESSAGE_REPORT_AUDIO_STATUS, oneByteValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR, new FixedLengthValidator(3), DEST_DIRECT)226 addValidationInfo(Constants.MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR, 227 new FixedLengthValidator(3), DEST_DIRECT); addValidationInfo(Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR, oneByteValidator, DEST_DIRECT)228 addValidationInfo(Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR, 229 oneByteValidator, DEST_DIRECT); addValidationInfo( Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, new OneByteRangeValidator(0x00, 0x01), DEST_ALL)230 addValidationInfo( 231 Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, 232 new OneByteRangeValidator(0x00, 0x01), 233 DEST_ALL); addValidationInfo( Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS, new OneByteRangeValidator(0x00, 0x01), DEST_DIRECT)234 addValidationInfo( 235 Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS, 236 new OneByteRangeValidator(0x00, 0x01), 237 DEST_DIRECT); 238 239 // Messages for the Audio Rate Control. addValidationInfo( Constants.MESSAGE_SET_AUDIO_RATE, new OneByteRangeValidator(0x00, 0x06), DEST_DIRECT)240 addValidationInfo( 241 Constants.MESSAGE_SET_AUDIO_RATE, 242 new OneByteRangeValidator(0x00, 0x06), 243 DEST_DIRECT); 244 245 // Messages for Feature Discovery. addValidationInfo(Constants.MESSAGE_GIVE_FEATURES, noneValidator, DEST_DIRECT | SRC_UNREGISTERED)246 addValidationInfo(Constants.MESSAGE_GIVE_FEATURES, noneValidator, 247 DEST_DIRECT | SRC_UNREGISTERED); 248 249 // Messages for Dynamic Auto Lipsync addValidationInfo(Constants.MESSAGE_REQUEST_CURRENT_LATENCY, physicalAddressValidator, DEST_BROADCAST)250 addValidationInfo(Constants.MESSAGE_REQUEST_CURRENT_LATENCY, physicalAddressValidator, 251 DEST_BROADCAST); addValidationInfo(Constants.MESSAGE_REPORT_CURRENT_LATENCY, new VariableLengthValidator(4, 14), DEST_BROADCAST)252 addValidationInfo(Constants.MESSAGE_REPORT_CURRENT_LATENCY, 253 new VariableLengthValidator(4, 14), DEST_BROADCAST); 254 255 // All Messages for the ARC have no parameters. 256 257 // Messages for the Capability Discovery and Control. addValidationInfo(Constants.MESSAGE_CDC_MESSAGE, maxLengthValidator, DEST_BROADCAST | SRC_UNREGISTERED)258 addValidationInfo(Constants.MESSAGE_CDC_MESSAGE, maxLengthValidator, 259 DEST_BROADCAST | SRC_UNREGISTERED); 260 } 261 addValidationInfo(int opcode, ParameterValidator validator, int addrType)262 private static void addValidationInfo(int opcode, ParameterValidator validator, int addrType) { 263 sValidationInfo.append(opcode, new ValidationInfo(validator, addrType)); 264 } 265 266 /** 267 * Validates all parameters of a HDMI-CEC message using static information stored in this class. 268 */ 269 @ValidationResult validate(int source, int destination, int opcode, byte[] params)270 static int validate(int source, int destination, int opcode, byte[] params) { 271 ValidationInfo info = sValidationInfo.get(opcode); 272 273 if (info == null) { 274 HdmiLogger.warning("No validation information for the opcode: " + opcode); 275 return OK; 276 } 277 278 int addressValidationResult = validateAddress(source, destination, info.addressType); 279 if (addressValidationResult != OK) { 280 return addressValidationResult; 281 } 282 283 // Validate parameters 284 int errorCode = info.parameterValidator.isValid(params); 285 if (errorCode != OK) { 286 return errorCode; 287 } 288 289 return OK; 290 } 291 292 /** 293 * Validates the source and destination addresses of a HDMI-CEC message according to input 294 * address type. Allows address validation logic to be expressed concisely without depending 295 * on static information in this class. 296 * @param source Source address to validate 297 * @param destination Destination address to validate 298 * @param addressType Rules for validating the addresses - e.g. {@link #DEST_BROADCAST} 299 */ 300 @ValidationResult validateAddress(int source, int destination, int addressType)301 static int validateAddress(int source, int destination, int addressType) { 302 // Check the source field. 303 if (source == Constants.ADDR_UNREGISTERED 304 && (addressType & SRC_UNREGISTERED) == 0) { 305 return ERROR_SOURCE; 306 } 307 308 // Check the destination field. 309 if (destination == Constants.ADDR_BROADCAST) { 310 if ((addressType & DEST_BROADCAST) == 0) { 311 return ERROR_DESTINATION; 312 } 313 } else { // Direct addressing. 314 if ((addressType & DEST_DIRECT) == 0) { 315 return ERROR_DESTINATION; 316 } 317 } 318 return OK; 319 } 320 321 private static class FixedLengthValidator implements ParameterValidator { 322 private final int mLength; 323 FixedLengthValidator(int length)324 public FixedLengthValidator(int length) { 325 mLength = length; 326 } 327 328 @Override isValid(byte[] params)329 public int isValid(byte[] params) { 330 // If the length is longer than expected, we assume it's OK since the parameter can be 331 // extended in the future version. 332 return params.length < mLength ? ERROR_PARAMETER_SHORT : OK; 333 } 334 } 335 336 private static class VariableLengthValidator implements ParameterValidator { 337 private final int mMinLength; 338 private final int mMaxLength; 339 VariableLengthValidator(int minLength, int maxLength)340 public VariableLengthValidator(int minLength, int maxLength) { 341 mMinLength = minLength; 342 mMaxLength = maxLength; 343 } 344 345 @Override isValid(byte[] params)346 public int isValid(byte[] params) { 347 return params.length < mMinLength ? ERROR_PARAMETER_SHORT : OK; 348 } 349 } 350 isValidPhysicalAddress(byte[] params, int offset)351 private static boolean isValidPhysicalAddress(byte[] params, int offset) { 352 int physicalAddress = HdmiUtils.twoBytesToInt(params, offset); 353 while (physicalAddress != 0) { 354 int maskedAddress = physicalAddress & 0xF000; 355 physicalAddress = (physicalAddress << 4) & 0xFFFF; 356 if (maskedAddress == 0 && physicalAddress != 0) { 357 return false; 358 } 359 } 360 return true; 361 } 362 363 /** 364 * Check if the given type is valid. A valid type is one of the actual logical device types 365 * defined in the standard ({@link HdmiDeviceInfo#DEVICE_TV}, 366 * {@link HdmiDeviceInfo#DEVICE_PLAYBACK}, {@link HdmiDeviceInfo#DEVICE_TUNER}, 367 * {@link HdmiDeviceInfo#DEVICE_RECORDER}, and {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM}). 368 * 369 * @param type device type 370 * @return true if the given type is valid 371 */ isValidType(int type)372 static boolean isValidType(int type) { 373 return (HdmiDeviceInfo.DEVICE_TV <= type 374 && type <= HdmiDeviceInfo.DEVICE_VIDEO_PROCESSOR) 375 && type != HdmiDeviceInfo.DEVICE_RESERVED; 376 } 377 toErrorCode(boolean success)378 private static int toErrorCode(boolean success) { 379 return success ? OK : ERROR_PARAMETER; 380 } 381 isWithinRange(int value, int min, int max)382 private static boolean isWithinRange(int value, int min, int max) { 383 value = value & 0xFF; 384 return (value >= min && value <= max); 385 } 386 387 /** 388 * Check if the given value is a valid Display Control. A valid value is one which falls within 389 * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 390 * 391 * @param value Display Control 392 * @return true if the Display Control is valid 393 */ isValidDisplayControl(int value)394 private static boolean isValidDisplayControl(int value) { 395 value = value & 0xFF; 396 return (value == 0x00 || value == 0x40 || value == 0x80 || value == 0xC0); 397 } 398 399 /** 400 * Check if the given params has valid ASCII characters. 401 * A valid ASCII character is a printable character. It should fall within range description 402 * defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 403 * 404 * @param params parameter consisting of string 405 * @param offset Start offset of string 406 * @param maxLength Maximum length of string to be evaluated 407 * @return true if the given type is valid 408 */ isValidAsciiString(byte[] params, int offset, int maxLength)409 private static boolean isValidAsciiString(byte[] params, int offset, int maxLength) { 410 for (int i = offset; i < params.length && i < maxLength; i++) { 411 if (!isWithinRange(params[i], 0x20, 0x7E)) { 412 return false; 413 } 414 } 415 return true; 416 } 417 418 /** 419 * Check if the given value is a valid day of month. A valid value is one which falls within the 420 * range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 421 * 422 * @param value day of month 423 * @return true if the day of month is valid 424 */ isValidDayOfMonth(int value)425 private static boolean isValidDayOfMonth(int value) { 426 return isWithinRange(value, 1, 31); 427 } 428 429 /** 430 * Check if the given value is a valid month of year. A valid value is one which falls within 431 * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 432 * 433 * @param value month of year 434 * @return true if the month of year is valid 435 */ isValidMonthOfYear(int value)436 private static boolean isValidMonthOfYear(int value) { 437 return isWithinRange(value, 1, 12); 438 } 439 440 /** 441 * Check if the given value is a valid hour. A valid value is one which falls within the range 442 * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 443 * 444 * @param value hour 445 * @return true if the hour is valid 446 */ isValidHour(int value)447 private static boolean isValidHour(int value) { 448 return isWithinRange(value, 0, 23); 449 } 450 451 /** 452 * Check if the given value is a valid minute. A valid value is one which falls within the range 453 * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 454 * 455 * @param value minute 456 * @return true if the minute is valid 457 */ isValidMinute(int value)458 private static boolean isValidMinute(int value) { 459 return isWithinRange(value, 0, 59); 460 } 461 462 /** 463 * Check if the given value is a valid duration hours. A valid value is one which falls within 464 * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 465 * 466 * @param value duration hours 467 * @return true if the duration hours is valid 468 */ isValidDurationHours(int value)469 private static boolean isValidDurationHours(int value) { 470 return isWithinRange(value, 0, 99); 471 } 472 473 /** 474 * Check if the given value is a valid recording sequence. A valid value is adheres to range 475 * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 476 * 477 * @param value recording sequence 478 * @return true if the given recording sequence is valid 479 */ isValidRecordingSequence(int value)480 private static boolean isValidRecordingSequence(int value) { 481 value = value & 0xFF; 482 // Validate bit 7 is set to zero 483 if ((value & 0x80) != 0x00) { 484 return false; 485 } 486 // Validate than not more than one bit is set 487 return (Integer.bitCount(value) <= 1); 488 } 489 490 /** 491 * Check if the given value is a valid analogue broadcast type. A valid value is one which falls 492 * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 493 * 17) 494 * 495 * @param value analogue broadcast type 496 * @return true if the analogue broadcast type is valid 497 */ isValidAnalogueBroadcastType(int value)498 private static boolean isValidAnalogueBroadcastType(int value) { 499 return isWithinRange(value, 0x00, 0x02); 500 } 501 502 /** 503 * Check if the given value is a valid analogue frequency. A valid value is one which falls 504 * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 505 * 17) 506 * 507 * @param value analogue frequency 508 * @return true if the analogue frequency is valid 509 */ isValidAnalogueFrequency(int value)510 private static boolean isValidAnalogueFrequency(int value) { 511 value = value & 0xFFFF; 512 return (value != 0x000 && value != 0xFFFF); 513 } 514 515 /** 516 * Check if the given value is a valid broadcast system. A valid value is one which falls within 517 * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 518 * 519 * @param value broadcast system 520 * @return true if the broadcast system is valid 521 */ isValidBroadcastSystem(int value)522 private static boolean isValidBroadcastSystem(int value) { 523 return isWithinRange(value, 0, 31); 524 } 525 526 /** 527 * Check if the given value is a ARIB type. A valid value is one which falls within the range 528 * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 529 * 530 * @param value Digital Broadcast System 531 * @return true if the Digital Broadcast System is ARIB type 532 */ isAribDbs(int value)533 private static boolean isAribDbs(int value) { 534 return (value == 0x00 || isWithinRange(value, 0x08, 0x0A)); 535 } 536 537 /** 538 * Check if the given value is a ATSC type. A valid value is one which falls within the range 539 * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 540 * 541 * @param value Digital Broadcast System 542 * @return true if the Digital Broadcast System is ATSC type 543 */ isAtscDbs(int value)544 private static boolean isAtscDbs(int value) { 545 return (value == 0x01 || isWithinRange(value, 0x10, 0x12)); 546 } 547 548 /** 549 * Check if the given value is a DVB type. A valid value is one which falls within the range 550 * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 551 * 552 * @param value Digital Broadcast System 553 * @return true if the Digital Broadcast System is DVB type 554 */ isDvbDbs(int value)555 private static boolean isDvbDbs(int value) { 556 return (value == 0x02 || isWithinRange(value, 0x18, 0x1B)); 557 } 558 559 /** 560 * Check if the given value is a valid Digital Broadcast System. A valid value is one which 561 * falls within the range description defined in CEC 1.4 Specification : Operand Descriptions 562 * (Section 17) 563 * 564 * @param value Digital Broadcast System 565 * @return true if the Digital Broadcast System is valid 566 */ isValidDigitalBroadcastSystem(int value)567 private static boolean isValidDigitalBroadcastSystem(int value) { 568 return (isAribDbs(value) || isAtscDbs(value) || isDvbDbs(value)); 569 } 570 571 /** 572 * Check if the given value is a valid Channel Identifier. A valid value is one which falls 573 * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 574 * 17) 575 * 576 * @param params Channel Identifier parameters 577 * @param offset start offset of Channel Identifier 578 * @return true if the Channel Identifier is valid 579 */ isValidChannelIdentifier(byte[] params, int offset)580 private static boolean isValidChannelIdentifier(byte[] params, int offset) { 581 // First 6 bits contain Channel Number Format 582 int channelNumberFormat = params[offset] & 0xFC; 583 if (channelNumberFormat == 0x04) { 584 // Validate it contains 1-part Channel Number data (16 bits) 585 return params.length - offset >= 3; 586 } else if (channelNumberFormat == 0x08) { 587 // Validate it contains Major Channel Number and Minor Channel Number (26 bits) 588 return params.length - offset >= 4; 589 } 590 return false; 591 } 592 593 /** 594 * Check if the given value is a valid Digital Service Identification. A valid value is one 595 * which falls within the range description defined in CEC 1.4 Specification : Operand 596 * Descriptions (Section 17) 597 * 598 * @param params Digital Timer Message parameters 599 * @param offset start offset of Digital Service Identification 600 * @return true if the Digital Service Identification is valid 601 */ isValidDigitalServiceIdentification(byte[] params, int offset)602 private static boolean isValidDigitalServiceIdentification(byte[] params, int offset) { 603 // MSB contains Service Identification Method 604 int serviceIdentificationMethod = params[offset] & 0x80; 605 // Last 7 bits contains Digital Broadcast System 606 int digitalBroadcastSystem = params[offset] & 0x7F; 607 offset = offset + 1; 608 if (serviceIdentificationMethod == 0x00) { 609 // Services identified by Digital IDs 610 if (isAribDbs(digitalBroadcastSystem)) { 611 // Validate ARIB type have 6 byte data 612 return params.length - offset >= 6; 613 } else if (isAtscDbs(digitalBroadcastSystem)) { 614 // Validate ATSC type have 4 byte data 615 return params.length - offset >= 4; 616 } else if (isDvbDbs(digitalBroadcastSystem)) { 617 // Validate DVB type have 6 byte data 618 return params.length - offset >= 6; 619 } 620 } else if (serviceIdentificationMethod == 0x80) { 621 // Services identified by Channel 622 if (isValidDigitalBroadcastSystem(digitalBroadcastSystem)) { 623 return isValidChannelIdentifier(params, offset); 624 } 625 } 626 return false; 627 } 628 629 /** 630 * Check if the given value is a valid External Plug. A valid value is one which falls within 631 * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 632 * 633 * @param value External Plug 634 * @return true if the External Plug is valid 635 */ isValidExternalPlug(int value)636 private static boolean isValidExternalPlug(int value) { 637 return isWithinRange(value, 1, 255); 638 } 639 640 /** 641 * Check if the given value is a valid External Source. A valid value is one which falls within 642 * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 643 * 644 * @param value External Source Specifier 645 * @return true if the External Source is valid 646 */ isValidExternalSource(byte[] params, int offset)647 private static boolean isValidExternalSource(byte[] params, int offset) { 648 int externalSourceSpecifier = params[offset]; 649 offset = offset + 1; 650 if (externalSourceSpecifier == 0x04) { 651 // External Plug 652 return isValidExternalPlug(params[offset]); 653 } else if (externalSourceSpecifier == 0x05) { 654 // External Physical Address 655 // Validate it contains 2 bytes Physical Address 656 if (params.length - offset >= 2) { 657 return isValidPhysicalAddress(params, offset); 658 } 659 } 660 return false; 661 } 662 isValidProgrammedInfo(int programedInfo)663 private static boolean isValidProgrammedInfo(int programedInfo) { 664 return (isWithinRange(programedInfo, 0x00, 0x0B)); 665 } 666 isValidNotProgrammedErrorInfo(int nonProgramedErrorInfo)667 private static boolean isValidNotProgrammedErrorInfo(int nonProgramedErrorInfo) { 668 return (isWithinRange(nonProgramedErrorInfo, 0x00, 0x0E)); 669 } 670 isValidTimerStatusData(byte[] params, int offset)671 private static boolean isValidTimerStatusData(byte[] params, int offset) { 672 int programedIndicator = params[offset] & 0x10; 673 boolean durationAvailable = false; 674 if (programedIndicator == 0x10) { 675 // Programmed 676 int programedInfo = params[offset] & 0x0F; 677 if (isValidProgrammedInfo(programedInfo)) { 678 if (programedInfo == 0x09 || programedInfo == 0x0B) { 679 durationAvailable = true; 680 } else { 681 return true; 682 } 683 } 684 } else { 685 // Non programmed 686 int nonProgramedErrorInfo = params[offset] & 0x0F; 687 if (isValidNotProgrammedErrorInfo(nonProgramedErrorInfo)) { 688 if (nonProgramedErrorInfo == 0x0E) { 689 durationAvailable = true; 690 } else { 691 return true; 692 } 693 } 694 } 695 offset = offset + 1; 696 // Duration Available (2 bytes) 697 if (durationAvailable && params.length - offset >= 2) { 698 return (isValidDurationHours(params[offset]) && isValidMinute(params[offset + 1])); 699 } 700 return false; 701 } 702 703 /** 704 * Check if the given value is a valid Play mode. A valid value is one which falls within the 705 * range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 706 * 707 * @param value Play mode 708 * @return true if the Play mode is valid 709 */ isValidPlayMode(int value)710 private static boolean isValidPlayMode(int value) { 711 return (isWithinRange(value, 0x05, 0x07) 712 || isWithinRange(value, 0x09, 0x0B) 713 || isWithinRange(value, 0x15, 0x17) 714 || isWithinRange(value, 0x19, 0x1B) 715 || isWithinRange(value, 0x24, 0x25) 716 || (value == 0x20)); 717 } 718 719 /** 720 * Check if the given value is a valid UI Broadcast type. A valid value is one which falls 721 * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 722 * 17) 723 * 724 * @param value UI Broadcast type 725 * @return true if the UI Broadcast type is valid 726 */ isValidUiBroadcastType(int value)727 private static boolean isValidUiBroadcastType(int value) { 728 return ((value == 0x00) 729 || (value == 0x01) 730 || (value == 0x10) 731 || (value == 0x20) 732 || (value == 0x30) 733 || (value == 0x40) 734 || (value == 0x50) 735 || (value == 0x60) 736 || (value == 0x70) 737 || (value == 0x80) 738 || (value == 0x90) 739 || (value == 0x91) 740 || (value == 0xA0)); 741 } 742 743 /** 744 * Check if the given value is a valid UI Sound Presenation Control. A valid value is one which 745 * falls within the range description defined in CEC 1.4 Specification : Operand Descriptions 746 * (Section 17) 747 * 748 * @param value UI Sound Presenation Control 749 * @return true if the UI Sound Presenation Control is valid 750 */ isValidUiSoundPresenationControl(int value)751 private static boolean isValidUiSoundPresenationControl(int value) { 752 value = value & 0xFF; 753 return ((value == 0x20) 754 || (value == 0x30) 755 || (value == 0x80) 756 || (value == 0x90) 757 || (value == 0xA0) 758 || (isWithinRange(value, 0xB1, 0xB3)) 759 || (isWithinRange(value, 0xC1, 0xC3))); 760 } 761 762 /* 763 * Check if the given value is a valid Tuner Device info. A valid value is one which falls 764 * within the range description defined in CEC 1.4 Specification : Operand Descriptions 765 * (Section 17) 766 * 767 * @param params Tuner device info 768 * @return true if the Tuner device info is valid 769 */ isValidTunerDeviceInfo(byte[] params)770 private static boolean isValidTunerDeviceInfo(byte[] params) { 771 int tunerDisplayInfo = params[0] & 0x7F; 772 if (tunerDisplayInfo == 0x00) { 773 // Displaying digital tuner 774 if (params.length >= 5) { 775 return isValidDigitalServiceIdentification(params, 1); 776 } 777 } else if (tunerDisplayInfo == 0x01) { 778 // Not displaying Tuner 779 return true; 780 } else if (tunerDisplayInfo == 0x02) { 781 // Displaying Analogue tuner 782 if (params.length >= 5) { 783 return (isValidAnalogueBroadcastType(params[1]) 784 && isValidAnalogueFrequency(HdmiUtils.twoBytesToInt(params, 2)) 785 && isValidBroadcastSystem(params[4])); 786 } 787 } 788 return false; 789 } 790 791 private static class PhysicalAddressValidator implements ParameterValidator { 792 @Override isValid(byte[] params)793 public int isValid(byte[] params) { 794 if (params.length < 2) { 795 return ERROR_PARAMETER_SHORT; 796 } 797 return toErrorCode(isValidPhysicalAddress(params, 0)); 798 } 799 } 800 801 private static class SystemAudioModeRequestValidator extends PhysicalAddressValidator { 802 @Override isValid(byte[] params)803 public int isValid(byte[] params) { 804 // TV can send <System Audio Mode Request> with no parameters to terminate system audio. 805 if (params.length == 0) { 806 return OK; 807 } 808 return super.isValid(params); 809 } 810 } 811 812 private static class ReportPhysicalAddressValidator implements ParameterValidator { 813 @Override isValid(byte[] params)814 public int isValid(byte[] params) { 815 if (params.length < 3) { 816 return ERROR_PARAMETER_SHORT; 817 } 818 return toErrorCode(isValidPhysicalAddress(params, 0) && isValidType(params[2])); 819 } 820 } 821 822 private static class RoutingChangeValidator implements ParameterValidator { 823 @Override isValid(byte[] params)824 public int isValid(byte[] params) { 825 if (params.length < 4) { 826 return ERROR_PARAMETER_SHORT; 827 } 828 return toErrorCode( 829 isValidPhysicalAddress(params, 0) && isValidPhysicalAddress(params, 2)); 830 } 831 } 832 833 /** 834 * Check if the given record status message parameter is valid. 835 * A valid parameter should lie within the range description of Record Status Info defined in 836 * CEC 1.4 Specification : Operand Descriptions (Section 17) 837 */ 838 private static class RecordStatusInfoValidator implements ParameterValidator { 839 @Override isValid(byte[] params)840 public int isValid(byte[] params) { 841 if (params.length < 1) { 842 return ERROR_PARAMETER_SHORT; 843 } 844 return toErrorCode(isWithinRange(params[0], 0x01, 0x07) 845 || isWithinRange(params[0], 0x09, 0x0E) 846 || isWithinRange(params[0], 0x10, 0x17) 847 || isWithinRange(params[0], 0x1A, 0x1B) 848 || params[0] == 0x1F); 849 } 850 } 851 852 /** 853 * Check if the given parameters represents printable characters. 854 * A valid parameter should lie within the range description of ASCII defined in CEC 1.4 855 * Specification : Operand Descriptions (Section 17) 856 */ 857 private static class AsciiValidator implements ParameterValidator { 858 private final int mMinLength; 859 private final int mMaxLength; 860 AsciiValidator(int length)861 AsciiValidator(int length) { 862 mMinLength = length; 863 mMaxLength = length; 864 } 865 AsciiValidator(int minLength, int maxLength)866 AsciiValidator(int minLength, int maxLength) { 867 mMinLength = minLength; 868 mMaxLength = maxLength; 869 } 870 871 @Override isValid(byte[] params)872 public int isValid(byte[] params) { 873 // If the length is longer than expected, we assume it's OK since the parameter can be 874 // extended in the future version. 875 if (params.length < mMinLength) { 876 return ERROR_PARAMETER_SHORT; 877 } 878 return toErrorCode(isValidAsciiString(params, 0, mMaxLength)); 879 } 880 } 881 882 /** 883 * Check if the given parameters is valid OSD String. 884 * A valid parameter should lie within the range description of ASCII defined in CEC 1.4 885 * Specification : Operand Descriptions (Section 17) 886 */ 887 private static class OsdStringValidator implements ParameterValidator { 888 @Override isValid(byte[] params)889 public int isValid(byte[] params) { 890 // If the length is longer than expected, we assume it's OK since the parameter can be 891 // extended in the future version. 892 if (params.length < 2) { 893 return ERROR_PARAMETER_SHORT; 894 } 895 return toErrorCode( 896 // Display Control 897 isValidDisplayControl(params[0]) 898 // OSD String 899 && isValidAsciiString(params, 1, 14)); 900 } 901 } 902 903 /** Check if the given parameters are one byte parameters and within range. */ 904 private static class OneByteRangeValidator implements ParameterValidator { 905 private final int mMinValue, mMaxValue; 906 OneByteRangeValidator(int minValue, int maxValue)907 OneByteRangeValidator(int minValue, int maxValue) { 908 mMinValue = minValue; 909 mMaxValue = maxValue; 910 } 911 912 @Override isValid(byte[] params)913 public int isValid(byte[] params) { 914 if (params.length < 1) { 915 return ERROR_PARAMETER_SHORT; 916 } 917 return toErrorCode(isWithinRange(params[0], mMinValue, mMaxValue)); 918 } 919 } 920 921 /** 922 * Check if the given Analogue Timer message parameters are valid. Valid parameters should 923 * adhere to message description of Analogue Timer defined in CEC 1.4 Specification : Message 924 * Descriptions for Timer Programming Feature (CEC Table 12) 925 */ 926 private static class AnalogueTimerValidator implements ParameterValidator { 927 @Override isValid(byte[] params)928 public int isValid(byte[] params) { 929 if (params.length < 11) { 930 return ERROR_PARAMETER_SHORT; 931 } 932 return toErrorCode( 933 isValidDayOfMonth(params[0]) // Day of Month 934 && isValidMonthOfYear(params[1]) // Month of Year 935 && isValidHour(params[2]) // Start Time - Hour 936 && isValidMinute(params[3]) // Start Time - Minute 937 && isValidDurationHours(params[4]) // Duration - Duration Hours 938 && isValidMinute(params[5]) // Duration - Minute 939 && isValidRecordingSequence(params[6]) // Recording Sequence 940 && isValidAnalogueBroadcastType(params[7]) // Analogue Broadcast Type 941 && isValidAnalogueFrequency( 942 HdmiUtils.twoBytesToInt(params, 8)) // Analogue Frequency 943 && isValidBroadcastSystem(params[10])); // Broadcast System 944 } 945 } 946 947 /** 948 * Check if the given Digital Timer message parameters are valid. Valid parameters should adhere 949 * to message description of Digital Timer defined in CEC 1.4 Specification : Message 950 * Descriptions for Timer Programming Feature (CEC Table 12) 951 */ 952 private static class DigitalTimerValidator implements ParameterValidator { 953 @Override isValid(byte[] params)954 public int isValid(byte[] params) { 955 if (params.length < 11) { 956 return ERROR_PARAMETER_SHORT; 957 } 958 return toErrorCode( 959 isValidDayOfMonth(params[0]) // Day of Month 960 && isValidMonthOfYear(params[1]) // Month of Year 961 && isValidHour(params[2]) // Start Time - Hour 962 && isValidMinute(params[3]) // Start Time - Minute 963 && isValidDurationHours(params[4]) // Duration - Duration Hours 964 && isValidMinute(params[5]) // Duration - Minute 965 && isValidRecordingSequence(params[6]) // Recording Sequence 966 && isValidDigitalServiceIdentification( 967 params, 7)); // Digital Service Identification 968 } 969 } 970 971 /** 972 * Check if the given External Timer message parameters are valid. Valid parameters should 973 * adhere to message description of External Timer defined in CEC 1.4 Specification : Message 974 * Descriptions for Timer Programming Feature (CEC Table 12) 975 */ 976 private static class ExternalTimerValidator implements ParameterValidator { 977 @Override isValid(byte[] params)978 public int isValid(byte[] params) { 979 if (params.length < 9) { 980 return ERROR_PARAMETER_SHORT; 981 } 982 return toErrorCode( 983 isValidDayOfMonth(params[0]) // Day of Month 984 && isValidMonthOfYear(params[1]) // Month of Year 985 && isValidHour(params[2]) // Start Time - Hour 986 && isValidMinute(params[3]) // Start Time - Minute 987 && isValidDurationHours(params[4]) // Duration - Duration Hours 988 && isValidMinute(params[5]) // Duration - Minute 989 && isValidRecordingSequence(params[6]) // Recording Sequence 990 && isValidExternalSource(params, 7)); // External Source 991 } 992 } 993 994 /** 995 * Check if the given timer cleared status parameter is valid. A valid parameter should lie 996 * within the range description defined in CEC 1.4 Specification : Operand Descriptions 997 * (Section 17) 998 */ 999 private static class TimerClearedStatusValidator implements ParameterValidator { 1000 @Override isValid(byte[] params)1001 public int isValid(byte[] params) { 1002 if (params.length < 1) { 1003 return ERROR_PARAMETER_SHORT; 1004 } 1005 return toErrorCode(isWithinRange(params[0], 0x00, 0x02) || (params[0] & 0xFF) == 0x80); 1006 } 1007 } 1008 1009 /** 1010 * Check if the given timer status data parameter is valid. A valid parameter should lie within 1011 * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 1012 */ 1013 private static class TimerStatusValidator implements ParameterValidator { 1014 @Override isValid(byte[] params)1015 public int isValid(byte[] params) { 1016 if (params.length < 1) { 1017 return ERROR_PARAMETER_SHORT; 1018 } 1019 return toErrorCode(isValidTimerStatusData(params, 0)); 1020 } 1021 } 1022 1023 /** 1024 * Check if the given play mode parameter is valid. A valid parameter should lie within the 1025 * range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) 1026 */ 1027 private static class PlayModeValidator implements ParameterValidator { 1028 @Override isValid(byte[] params)1029 public int isValid(byte[] params) { 1030 if (params.length < 1) { 1031 return ERROR_PARAMETER_SHORT; 1032 } 1033 return toErrorCode(isValidPlayMode(params[0])); 1034 } 1035 } 1036 1037 /** 1038 * Check if the given select analogue service parameter is valid. A valid parameter should lie 1039 * within the range description defined in CEC 1.4 Specification : Operand Descriptions 1040 * (Section 17) 1041 */ 1042 private static class SelectAnalogueServiceValidator implements ParameterValidator { 1043 @Override isValid(byte[] params)1044 public int isValid(byte[] params) { 1045 if (params.length < 4) { 1046 return ERROR_PARAMETER_SHORT; 1047 } 1048 return toErrorCode(isValidAnalogueBroadcastType(params[0]) 1049 && isValidAnalogueFrequency(HdmiUtils.twoBytesToInt(params, 1)) 1050 && isValidBroadcastSystem(params[3])); 1051 } 1052 } 1053 1054 /** 1055 * Check if the given select digital service parameter is valid. A valid parameter should lie 1056 * within the range description defined in CEC 1.4 Specification : Operand Descriptions 1057 * (Section 17) 1058 */ 1059 private static class SelectDigitalServiceValidator implements ParameterValidator { 1060 @Override isValid(byte[] params)1061 public int isValid(byte[] params) { 1062 if (params.length < 4) { 1063 return ERROR_PARAMETER_SHORT; 1064 } 1065 return toErrorCode(isValidDigitalServiceIdentification(params, 0)); 1066 } 1067 } 1068 1069 /** 1070 * Check if the given tuner device status parameter is valid. A valid parameter should lie 1071 * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 1072 * 17) 1073 */ 1074 private static class TunerDeviceStatusValidator implements ParameterValidator { 1075 @Override isValid(byte[] params)1076 public int isValid(byte[] params) { 1077 if (params.length < 1) { 1078 return ERROR_PARAMETER_SHORT; 1079 } 1080 return toErrorCode(isValidTunerDeviceInfo(params)); 1081 } 1082 } 1083 1084 /** Check if the given user control press parameter is valid. */ 1085 private static class UserControlPressedValidator implements ParameterValidator { 1086 @Override isValid(byte[] params)1087 public int isValid(byte[] params) { 1088 if (params.length < 1) { 1089 return ERROR_PARAMETER_SHORT; 1090 } 1091 if (params.length == 1) { 1092 return OK; 1093 } 1094 int uiCommand = params[0]; 1095 switch (uiCommand) { 1096 case HdmiCecKeycode.CEC_KEYCODE_PLAY_FUNCTION: 1097 return toErrorCode(isValidPlayMode(params[1])); 1098 case HdmiCecKeycode.CEC_KEYCODE_TUNE_FUNCTION: 1099 return (params.length >= 4 1100 ? toErrorCode(isValidChannelIdentifier(params, 1)) 1101 : ERROR_PARAMETER_SHORT); 1102 case HdmiCecKeycode.CEC_KEYCODE_SELECT_BROADCAST_TYPE: 1103 return toErrorCode(isValidUiBroadcastType(params[1])); 1104 case HdmiCecKeycode.CEC_KEYCODE_SELECT_SOUND_PRESENTATION: 1105 return toErrorCode(isValidUiSoundPresenationControl(params[1])); 1106 default: 1107 return OK; 1108 } 1109 } 1110 } 1111 } 1112