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.Nullable; 20 21 import libcore.util.EmptyArray; 22 23 import java.util.Arrays; 24 import java.util.Objects; 25 26 /** 27 * A class to encapsulate HDMI-CEC message used for the devices connected via 28 * HDMI cable to communicate with one another. A message is defined by its 29 * source and destination address, command (or opcode), and optional parameters. 30 */ 31 public final class HdmiCecMessage { 32 public static final byte[] EMPTY_PARAM = EmptyArray.BYTE; 33 34 private final int mSource; 35 private final int mDestination; 36 37 private final int mOpcode; 38 private final byte[] mParams; 39 40 /** 41 * Constructor. 42 */ HdmiCecMessage(int source, int destination, int opcode, byte[] params)43 public HdmiCecMessage(int source, int destination, int opcode, byte[] params) { 44 mSource = source; 45 mDestination = destination; 46 mOpcode = opcode & 0xFF; 47 mParams = Arrays.copyOf(params, params.length); 48 } 49 50 @Override equals(@ullable Object message)51 public boolean equals(@Nullable Object message) { 52 if (message instanceof HdmiCecMessage) { 53 HdmiCecMessage that = (HdmiCecMessage) message; 54 return this.mSource == that.getSource() && 55 this.mDestination == that.getDestination() && 56 this.mOpcode == that.getOpcode() && 57 Arrays.equals(this.mParams, that.getParams()); 58 } 59 return false; 60 } 61 62 @Override hashCode()63 public int hashCode() { 64 return Objects.hash( 65 mSource, 66 mDestination, 67 mOpcode, 68 Arrays.hashCode(mParams)); 69 } 70 71 /** 72 * Return the source address field of the message. It is the logical address 73 * of the device which generated the message. 74 * 75 * @return source address 76 */ getSource()77 public int getSource() { 78 return mSource; 79 } 80 81 /** 82 * Return the destination address field of the message. It is the logical address 83 * of the device to which the message is sent. 84 * 85 * @return destination address 86 */ getDestination()87 public int getDestination() { 88 return mDestination; 89 } 90 91 /** 92 * Return the opcode field of the message. It is the type of the message that 93 * tells the destination device what to do. 94 * 95 * @return opcode 96 */ getOpcode()97 public int getOpcode() { 98 return mOpcode; 99 } 100 101 /** 102 * Return the parameter field of the message. The contents of parameter varies 103 * from opcode to opcode, and is used together with opcode to describe 104 * the action for the destination device to take. 105 * 106 * @return parameter 107 */ getParams()108 public byte[] getParams() { 109 return mParams; 110 } 111 112 @Override toString()113 public String toString() { 114 StringBuffer s = new StringBuffer(); 115 s.append(String.format("<%s> %X%X:%02X", 116 opcodeToString(mOpcode), mSource, mDestination, mOpcode)); 117 if (mParams.length > 0) { 118 if (filterMessageParameters(mOpcode)) { 119 s.append(String.format(" <Redacted len=%d>", mParams.length)); 120 } else { 121 for (byte data : mParams) { 122 s.append(String.format(":%02X", data)); 123 } 124 } 125 } 126 return s.toString(); 127 } 128 opcodeToString(int opcode)129 private static String opcodeToString(int opcode) { 130 switch (opcode) { 131 case Constants.MESSAGE_FEATURE_ABORT: 132 return "Feature Abort"; 133 case Constants.MESSAGE_IMAGE_VIEW_ON: 134 return "Image View On"; 135 case Constants.MESSAGE_TUNER_STEP_INCREMENT: 136 return "Tuner Step Increment"; 137 case Constants.MESSAGE_TUNER_STEP_DECREMENT: 138 return "Tuner Step Decrement"; 139 case Constants.MESSAGE_TUNER_DEVICE_STATUS: 140 return "Tuner Device Status"; 141 case Constants.MESSAGE_GIVE_TUNER_DEVICE_STATUS: 142 return "Give Tuner Device Status"; 143 case Constants.MESSAGE_RECORD_ON: 144 return "Record On"; 145 case Constants.MESSAGE_RECORD_STATUS: 146 return "Record Status"; 147 case Constants.MESSAGE_RECORD_OFF: 148 return "Record Off"; 149 case Constants.MESSAGE_TEXT_VIEW_ON: 150 return "Text View On"; 151 case Constants.MESSAGE_RECORD_TV_SCREEN: 152 return "Record Tv Screen"; 153 case Constants.MESSAGE_GIVE_DECK_STATUS: 154 return "Give Deck Status"; 155 case Constants.MESSAGE_DECK_STATUS: 156 return "Deck Status"; 157 case Constants.MESSAGE_SET_MENU_LANGUAGE: 158 return "Set Menu Language"; 159 case Constants.MESSAGE_CLEAR_ANALOG_TIMER: 160 return "Clear Analog Timer"; 161 case Constants.MESSAGE_SET_ANALOG_TIMER: 162 return "Set Analog Timer"; 163 case Constants.MESSAGE_TIMER_STATUS: 164 return "Timer Status"; 165 case Constants.MESSAGE_STANDBY: 166 return "Standby"; 167 case Constants.MESSAGE_PLAY: 168 return "Play"; 169 case Constants.MESSAGE_DECK_CONTROL: 170 return "Deck Control"; 171 case Constants.MESSAGE_TIMER_CLEARED_STATUS: 172 return "Timer Cleared Status"; 173 case Constants.MESSAGE_USER_CONTROL_PRESSED: 174 return "User Control Pressed"; 175 case Constants.MESSAGE_USER_CONTROL_RELEASED: 176 return "User Control Release"; 177 case Constants.MESSAGE_GIVE_OSD_NAME: 178 return "Give Osd Name"; 179 case Constants.MESSAGE_SET_OSD_NAME: 180 return "Set Osd Name"; 181 case Constants.MESSAGE_SET_OSD_STRING: 182 return "Set Osd String"; 183 case Constants.MESSAGE_SET_TIMER_PROGRAM_TITLE: 184 return "Set Timer Program Title"; 185 case Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST: 186 return "System Audio Mode Request"; 187 case Constants.MESSAGE_GIVE_AUDIO_STATUS: 188 return "Give Audio Status"; 189 case Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE: 190 return "Set System Audio Mode"; 191 case Constants.MESSAGE_REPORT_AUDIO_STATUS: 192 return "Report Audio Status"; 193 case Constants.MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS: 194 return "Give System Audio Mode Status"; 195 case Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS: 196 return "System Audio Mode Status"; 197 case Constants.MESSAGE_ROUTING_CHANGE: 198 return "Routing Change"; 199 case Constants.MESSAGE_ROUTING_INFORMATION: 200 return "Routing Information"; 201 case Constants.MESSAGE_ACTIVE_SOURCE: 202 return "Active Source"; 203 case Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS: 204 return "Give Physical Address"; 205 case Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS: 206 return "Report Physical Address"; 207 case Constants.MESSAGE_REQUEST_ACTIVE_SOURCE: 208 return "Request Active Source"; 209 case Constants.MESSAGE_SET_STREAM_PATH: 210 return "Set Stream Path"; 211 case Constants.MESSAGE_DEVICE_VENDOR_ID: 212 return "Device Vendor Id"; 213 case Constants.MESSAGE_VENDOR_COMMAND: 214 return "Vendor Command"; 215 case Constants.MESSAGE_VENDOR_REMOTE_BUTTON_DOWN: 216 return "Vendor Remote Button Down"; 217 case Constants.MESSAGE_VENDOR_REMOTE_BUTTON_UP: 218 return "Vendor Remote Button Up"; 219 case Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID: 220 return "Give Device Vendor Id"; 221 case Constants.MESSAGE_MENU_REQUEST: 222 return "Menu Request"; 223 case Constants.MESSAGE_MENU_STATUS: 224 return "Menu Status"; 225 case Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS: 226 return "Give Device Power Status"; 227 case Constants.MESSAGE_REPORT_POWER_STATUS: 228 return "Report Power Status"; 229 case Constants.MESSAGE_GET_MENU_LANGUAGE: 230 return "Get Menu Language"; 231 case Constants.MESSAGE_SELECT_ANALOG_SERVICE: 232 return "Select Analog Service"; 233 case Constants.MESSAGE_SELECT_DIGITAL_SERVICE: 234 return "Select Digital Service"; 235 case Constants.MESSAGE_SET_DIGITAL_TIMER: 236 return "Set Digital Timer"; 237 case Constants.MESSAGE_CLEAR_DIGITAL_TIMER: 238 return "Clear Digital Timer"; 239 case Constants.MESSAGE_SET_AUDIO_RATE: 240 return "Set Audio Rate"; 241 case Constants.MESSAGE_INACTIVE_SOURCE: 242 return "InActive Source"; 243 case Constants.MESSAGE_CEC_VERSION: 244 return "Cec Version"; 245 case Constants.MESSAGE_GET_CEC_VERSION: 246 return "Get Cec Version"; 247 case Constants.MESSAGE_VENDOR_COMMAND_WITH_ID: 248 return "Vendor Command With Id"; 249 case Constants.MESSAGE_CLEAR_EXTERNAL_TIMER: 250 return "Clear External Timer"; 251 case Constants.MESSAGE_SET_EXTERNAL_TIMER: 252 return "Set External Timer"; 253 case Constants.MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR: 254 return "Report Short Audio Descriptor"; 255 case Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR: 256 return "Request Short Audio Descriptor"; 257 case Constants.MESSAGE_INITIATE_ARC: 258 return "Initiate ARC"; 259 case Constants.MESSAGE_REPORT_ARC_INITIATED: 260 return "Report ARC Initiated"; 261 case Constants.MESSAGE_REPORT_ARC_TERMINATED: 262 return "Report ARC Terminated"; 263 case Constants.MESSAGE_REQUEST_ARC_INITIATION: 264 return "Request ARC Initiation"; 265 case Constants.MESSAGE_REQUEST_ARC_TERMINATION: 266 return "Request ARC Termination"; 267 case Constants.MESSAGE_TERMINATE_ARC: 268 return "Terminate ARC"; 269 case Constants.MESSAGE_CDC_MESSAGE: 270 return "Cdc Message"; 271 case Constants.MESSAGE_ABORT: 272 return "Abort"; 273 default: 274 return String.format("Opcode: %02X", opcode); 275 } 276 } 277 filterMessageParameters(int opcode)278 private static boolean filterMessageParameters(int opcode) { 279 switch (opcode) { 280 case Constants.MESSAGE_USER_CONTROL_PRESSED: 281 case Constants.MESSAGE_USER_CONTROL_RELEASED: 282 case Constants.MESSAGE_SET_OSD_NAME: 283 case Constants.MESSAGE_SET_OSD_STRING: 284 case Constants.MESSAGE_VENDOR_COMMAND: 285 case Constants.MESSAGE_VENDOR_REMOTE_BUTTON_DOWN: 286 case Constants.MESSAGE_VENDOR_REMOTE_BUTTON_UP: 287 case Constants.MESSAGE_VENDOR_COMMAND_WITH_ID: 288 return true; 289 default: 290 return false; 291 } 292 } 293 } 294 295