HdmiCecMessageBuilder.java revision a6ce7708d6124224399241503fadcafe0c4684d4
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 17package com.android.server.hdmi; 18 19import android.hardware.hdmi.HdmiCec; 20import android.hardware.hdmi.HdmiCecMessage; 21 22import java.io.UnsupportedEncodingException; 23import java.util.Arrays; 24 25/** 26 * A helper class to build {@link HdmiCecMessage} from various cec commands. 27 */ 28public class HdmiCecMessageBuilder { 29 private static final int OSD_NAME_MAX_LENGTH = 13; 30 31 private HdmiCecMessageBuilder() {} 32 33 /** 34 * Build {@link HdmiCecMessage} from raw data. 35 * 36 * @param src source address of command 37 * @param dest destination address of command 38 * @param body body of message. It includes opcode. 39 * @return newly created {@link HdmiCecMessage} 40 */ 41 static HdmiCecMessage of(int src, int dest, byte[] body) { 42 byte opcode = body[0]; 43 byte params[] = Arrays.copyOfRange(body, 1, body.length); 44 return new HdmiCecMessage(src, dest, opcode, params); 45 } 46 47 /** 48 * Build <Feature Abort> command. <Feature Abort> consists of 49 * 1 byte original opcode and 1 byte reason fields with basic fields. 50 * 51 * @param src source address of command 52 * @param dest destination address of command 53 * @param originalOpcode original opcode causing feature abort 54 * @param reason reason of feature abort 55 * @return newly created {@link HdmiCecMessage} 56 */ 57 static HdmiCecMessage buildFeatureAbortCommand(int src, int dest, int originalOpcode, 58 int reason) { 59 byte[] params = new byte[] { 60 (byte) originalOpcode, 61 (byte) reason, 62 }; 63 return buildCommand(src, dest, HdmiCec.MESSAGE_FEATURE_ABORT, params); 64 } 65 66 /** 67 * Build <Give Physical Address> command. 68 * 69 * @param src source address of command 70 * @param dest destination address of command 71 * @return newly created {@link HdmiCecMessage} 72 */ 73 static HdmiCecMessage buildGivePhysicalAddress(int src, int dest) { 74 return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_PHYSICAL_ADDRESS); 75 } 76 77 /** 78 * Build <Give Osd Name> command. 79 * 80 * @param src source address of command 81 * @param dest destination address of command 82 * @return newly created {@link HdmiCecMessage} 83 */ 84 static HdmiCecMessage buildGiveOsdNameCommand(int src, int dest) { 85 return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_OSD_NAME); 86 } 87 88 /** 89 * Build <Give Vendor Id Command> command. 90 * 91 * @param src source address of command 92 * @param dest destination address of command 93 * @return newly created {@link HdmiCecMessage} 94 */ 95 static HdmiCecMessage buildGiveDeviceVendorIdCommand(int src, int dest) { 96 return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_DEVICE_VENDOR_ID); 97 } 98 99 /** 100 * Build <Set Menu Language > command. 101 * 102 * <p>This is a broadcast message sent to all devices on the bus. 103 * 104 * @param src source address of command 105 * @param language 3-letter ISO639-2 based language code 106 * @return newly created {@link HdmiCecMessage} if language is valid. 107 * Otherwise, return null 108 */ 109 static HdmiCecMessage buildSetMenuLanguageCommand(int src, String language) { 110 if (language.length() != 3) { 111 return null; 112 } 113 // Hdmi CEC uses lower-cased ISO 639-2 (3 letters code). 114 String normalized = language.toLowerCase(); 115 byte[] params = new byte[] { 116 (byte) normalized.charAt(0), 117 (byte) normalized.charAt(1), 118 (byte) normalized.charAt(2), 119 }; 120 // <Set Menu Language> is broadcast message. 121 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_SET_MENU_LANGUAGE, 122 params); 123 } 124 125 /** 126 * Build <Set Osd Name > command. 127 * 128 * @param src source address of command 129 * @param name display (OSD) name of device 130 * @return newly created {@link HdmiCecMessage} if valid name. Otherwise, 131 * return null 132 */ 133 static HdmiCecMessage buildSetOsdNameCommand(int src, int dest, String name) { 134 int length = Math.min(name.length(), OSD_NAME_MAX_LENGTH); 135 byte[] params; 136 try { 137 params = name.substring(0, length).getBytes("US-ASCII"); 138 } catch (UnsupportedEncodingException e) { 139 return null; 140 } 141 return buildCommand(src, dest, HdmiCec.MESSAGE_SET_OSD_NAME, params); 142 } 143 144 /** 145 * Build <Report Physical Address> command. It has two bytes physical 146 * address and one byte device type as parameter. 147 * 148 * <p>This is a broadcast message sent to all devices on the bus. 149 * 150 * @param src source address of command 151 * @param address physical address of device 152 * @param deviceType type of device 153 * @return newly created {@link HdmiCecMessage} 154 */ 155 static HdmiCecMessage buildReportPhysicalAddressCommand(int src, int address, int deviceType) { 156 byte[] params = new byte[] { 157 // Two bytes for physical address 158 (byte) ((address >> 8) & 0xFF), 159 (byte) (address & 0xFF), 160 // One byte device type 161 (byte) deviceType 162 }; 163 // <Report Physical Address> is broadcast message. 164 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS, 165 params); 166 } 167 168 /** 169 * Build <Device Vendor Id> command. It has three bytes vendor id as 170 * parameter. 171 * 172 * <p>This is a broadcast message sent to all devices on the bus. 173 * 174 * @param src source address of command 175 * @param vendorId device's vendor id 176 * @return newly created {@link HdmiCecMessage} 177 */ 178 static HdmiCecMessage buildDeviceVendorIdCommand(int src, int vendorId) { 179 byte[] params = new byte[] { 180 (byte) ((vendorId >> 16) & 0xFF), 181 (byte) ((vendorId >> 8) & 0xFF), 182 (byte) (vendorId & 0xFF) 183 }; 184 // <Device Vendor Id> is broadcast message. 185 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_DEVICE_VENDOR_ID, 186 params); 187 } 188 189 /** 190 * Build <Device Vendor Id> command. It has one byte cec version as parameter. 191 * 192 * @param src source address of command 193 * @param dest destination address of command 194 * @param version version of cec. Use 0x04 for "Version 1.3a" and 0x05 for 195 * "Version 1.4 or 1.4a or 1.4b 196 * @return newly created {@link HdmiCecMessage} 197 */ 198 static HdmiCecMessage buildCecVersion(int src, int dest, int version) { 199 byte[] params = new byte[] { 200 (byte) version 201 }; 202 return buildCommand(src, dest, HdmiCec.MESSAGE_CEC_VERSION, params); 203 } 204 205 /** 206 * Build <Request Arc Initiation> 207 * 208 * @param src source address of command 209 * @param dest destination address of command 210 * @return newly created {@link HdmiCecMessage} 211 */ 212 static HdmiCecMessage buildRequestArcInitiation(int src, int dest) { 213 return buildCommand(src, dest, HdmiCec.MESSAGE_REQUEST_ARC_INITIATION); 214 } 215 216 /** 217 * Build <Request Arc Termination> 218 * 219 * @param src source address of command 220 * @param dest destination address of command 221 * @return newly created {@link HdmiCecMessage} 222 */ 223 static HdmiCecMessage buildRequestArcTermination(int src, int dest) { 224 return buildCommand(src, dest, HdmiCec.MESSAGE_REQUEST_ARC_TERMINATION); 225 } 226 227 /** 228 * Build <Report Arc Initiated> 229 * 230 * @param src source address of command 231 * @param dest destination address of command 232 * @return newly created {@link HdmiCecMessage} 233 */ 234 static HdmiCecMessage buildReportArcInitiated(int src, int dest) { 235 return buildCommand(src, dest, HdmiCec.MESSAGE_REPORT_ARC_INITIATED); 236 } 237 238 /** 239 * Build <Report Arc Terminated> 240 * 241 * @param src source address of command 242 * @param dest destination address of command 243 * @return newly created {@link HdmiCecMessage} 244 */ 245 static HdmiCecMessage buildReportArcTerminated(int src, int dest) { 246 return buildCommand(src, dest, HdmiCec.MESSAGE_REPORT_ARC_TERMINATED); 247 } 248 249 /** 250 * Build <Text View On> command. 251 * 252 * @param src source address of command 253 * @param dest destination address of command 254 * @return newly created {@link HdmiCecMessage} 255 */ 256 static HdmiCecMessage buildTextViewOn(int src, int dest) { 257 return buildCommand(src, dest, HdmiCec.MESSAGE_TEXT_VIEW_ON); 258 } 259 260 /** 261 * Build <Active Source> command. 262 * 263 * @param src source address of command 264 * @param physicalAddress physical address of the device to become active 265 * @return newly created {@link HdmiCecMessage} 266 */ 267 static HdmiCecMessage buildActiveSource(int src, int physicalAddress) { 268 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_ACTIVE_SOURCE, 269 physicalAddressToParam(physicalAddress)); 270 } 271 272 /** 273 * Build <Set Stream Path> command. 274 * 275 * <p>This is a broadcast message sent to all devices on the bus. 276 * 277 * @param src source address of command 278 * @param streamPath physical address of the device to start streaming 279 * @return newly created {@link HdmiCecMessage} 280 */ 281 static HdmiCecMessage buildSetStreamPath(int src, int streamPath) { 282 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_SET_STREAM_PATH, 283 physicalAddressToParam(streamPath)); 284 } 285 286 /** 287 * Build <Routing Change> command. 288 * 289 * <p>This is a broadcast message sent to all devices on the bus. 290 * 291 * @param src source address of command 292 * @param oldPath physical address of the currently active routing path 293 * @param newPath physical address of the new active routing path 294 * @return newly created {@link HdmiCecMessage} 295 */ 296 static HdmiCecMessage buildRoutingChange(int src, int oldPath, int newPath) { 297 byte[] param = new byte[] { 298 (byte) ((oldPath >> 8) & 0xFF), (byte) (oldPath & 0xFF), 299 (byte) ((newPath >> 8) & 0xFF), (byte) (newPath & 0xFF) 300 }; 301 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_ROUTING_CHANGE, param); 302 } 303 304 /** 305 * Build <Give Device Power Status> command. 306 * 307 * @param src source address of command 308 * @param dest destination address of command 309 * @return newly created {@link HdmiCecMessage} 310 */ 311 static HdmiCecMessage buildGiveDevicePowerStatus(int src, int dest) { 312 return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS); 313 } 314 315 /** 316 * Build <System Audio Mode Request> command. 317 * 318 * @param src source address of command 319 * @param avr destination address of command, it should be AVR 320 * @param avrPhysicalAddress physical address of AVR 321 * @param enableSystemAudio whether to enable System Audio Mode or not 322 * @return newly created {@link HdmiCecMessage} 323 */ 324 static HdmiCecMessage buildSystemAudioModeRequest(int src, int avr, int avrPhysicalAddress, 325 boolean enableSystemAudio) { 326 if (enableSystemAudio) { 327 return buildCommand(src, avr, HdmiCec.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST, 328 physicalAddressToParam(avrPhysicalAddress)); 329 } else { 330 return buildCommand(src, avr, HdmiCec.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST); 331 } 332 } 333 334 /** 335 * Build <Give Audio Status> command. 336 * 337 * @param src source address of command 338 * @param dest destination address of command 339 * @return newly created {@link HdmiCecMessage} 340 */ 341 static HdmiCecMessage buildGiveAudioStatus(int src, int dest) { 342 return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_AUDIO_STATUS); 343 } 344 345 /** 346 * Build <User Control Pressed> command. 347 * 348 * @param src source address of command 349 * @param dest destination address of command 350 * @param uiCommand keycode that user pressed 351 * @return newly created {@link HdmiCecMessage} 352 */ 353 static HdmiCecMessage buildUserControlPressed(int src, int dest, int uiCommand) { 354 return buildUserControlPressed(src, dest, new byte[] { (byte) uiCommand }); 355 } 356 357 /** 358 * Build <User Control Pressed> command. 359 * 360 * @param src source address of command 361 * @param dest destination address of command 362 * @param commandParam uiCommand and the additional parameter 363 * @return newly created {@link HdmiCecMessage} 364 */ 365 static HdmiCecMessage buildUserControlPressed(int src, int dest, byte[] commandParam) { 366 return buildCommand(src, dest, HdmiCec.MESSAGE_USER_CONTROL_PRESSED, commandParam); 367 } 368 369 /** 370 * Build <User Control Released> command. 371 * 372 * @param src source address of command 373 * @param dest destination address of command 374 * @return newly created {@link HdmiCecMessage} 375 */ 376 static HdmiCecMessage buildUserControlReleased(int src, int dest) { 377 return buildCommand(src, dest, HdmiCec.MESSAGE_USER_CONTROL_RELEASED); 378 } 379 380 /***** Please ADD new buildXXX() methods above. ******/ 381 382 /** 383 * Build a {@link HdmiCecMessage} without extra parameter. 384 * 385 * @param src source address of command 386 * @param dest destination address of command 387 * @param opcode opcode for a message 388 * @return newly created {@link HdmiCecMessage} 389 */ 390 private static HdmiCecMessage buildCommand(int src, int dest, int opcode) { 391 return new HdmiCecMessage(src, dest, opcode, HdmiCecMessage.EMPTY_PARAM); 392 } 393 394 /** 395 * Build a {@link HdmiCecMessage} with given values. 396 * 397 * @param src source address of command 398 * @param dest destination address of command 399 * @param opcode opcode for a message 400 * @param params extra parameters for command 401 * @return newly created {@link HdmiCecMessage} 402 */ 403 private static HdmiCecMessage buildCommand(int src, int dest, int opcode, byte[] params) { 404 return new HdmiCecMessage(src, dest, opcode, params); 405 } 406 407 private static byte[] physicalAddressToParam(int physicalAddress) { 408 return new byte[] { 409 (byte) (physicalAddress >> 8), 410 (byte) (physicalAddress & 0xFF) 411 }; 412 } 413} 414