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