HdmiCecMessageBuilder.java revision c47e26ca2ff6f032c4b3a094810b1d1062bcb1ff
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 // TODO: move these values to HdmiCec.java once make it internal constant class. 30 // CEC's ABORT reason values. 31 static final int ABORT_UNRECOGNIZED_MODE = 0; 32 static final int ABORT_NOT_IN_CORRECT_MODE = 1; 33 static final int ABORT_CANNOT_PROVIDE_SOURCE = 2; 34 static final int ABORT_INVALID_OPERAND = 3; 35 static final int ABORT_REFUSED = 4; 36 static final int ABORT_UNABLE_TO_DETERMINE = 5; 37 38 private static final int OSD_NAME_MAX_LENGTH = 13; 39 40 private HdmiCecMessageBuilder() {} 41 42 /** 43 * Build {@link HdmiCecMessage} from raw data. 44 * 45 * @param src source address of command 46 * @param dest destination address of command 47 * @param body body of message. It includes opcode. 48 * @return newly created {@link HdmiCecMessage} 49 */ 50 static HdmiCecMessage of(int src, int dest, byte[] body) { 51 byte opcode = body[0]; 52 byte params[] = Arrays.copyOfRange(body, 1, body.length); 53 return new HdmiCecMessage(src, dest, opcode, params); 54 } 55 56 /** 57 * Build <Feature Abort> command. <Feature Abort> consists of 58 * 1 byte original opcode and 1 byte reason fields with basic fields. 59 * 60 * @param src source address of command 61 * @param dest destination address of command 62 * @param originalOpcode original opcode causing feature abort 63 * @param reason reason of feature abort 64 * @return newly created {@link HdmiCecMessage} 65 */ 66 static HdmiCecMessage buildFeatureAbortCommand(int src, int dest, int originalOpcode, 67 int reason) { 68 byte[] params = new byte[] { 69 (byte) originalOpcode, 70 (byte) reason, 71 }; 72 return buildCommand(src, dest, HdmiCec.MESSAGE_FEATURE_ABORT, params); 73 } 74 75 /** 76 * Build <Give Osd Name> command. 77 * 78 * @param src source address of command 79 * @param dest destination address of command 80 * @return newly created {@link HdmiCecMessage} 81 */ 82 static HdmiCecMessage buildGiveOsdNameCommand(int src, int dest) { 83 return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_OSD_NAME); 84 } 85 86 /** 87 * Build <Give Vendor Id Command> command. 88 * 89 * @param src source address of command 90 * @param dest destination address of command 91 * @return newly created {@link HdmiCecMessage} 92 */ 93 static HdmiCecMessage buildGiveDeviceVendorIdCommand(int src, int dest) { 94 return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_DEVICE_VENDOR_ID); 95 } 96 97 /** 98 * Build <Set Menu Language > command. 99 * 100 * <p>This is a broadcast message sent to all devices on the bus. 101 * 102 * @param src source address of command 103 * @param language 3-letter ISO639-2 based language code 104 * @return newly created {@link HdmiCecMessage} if language is valid. 105 * Otherwise, return null 106 */ 107 static HdmiCecMessage buildSetMenuLanguageCommand(int src, String language) { 108 if (language.length() != 3) { 109 return null; 110 } 111 // Hdmi CEC uses lower-cased ISO 639-2 (3 letters code). 112 String normalized = language.toLowerCase(); 113 byte[] params = new byte[] { 114 (byte) normalized.charAt(0), 115 (byte) normalized.charAt(1), 116 (byte) normalized.charAt(2), 117 }; 118 // <Set Menu Language> is broadcast message. 119 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_SET_MENU_LANGUAGE, 120 params); 121 } 122 123 /** 124 * Build <Set Osd Name > command. 125 * 126 * @param src source address of command 127 * @param name display (OSD) name of device 128 * @return newly created {@link HdmiCecMessage} if valid name. Otherwise, 129 * return null 130 */ 131 static HdmiCecMessage buildSetOsdNameCommand(int src, int dest, String name) { 132 int length = Math.min(name.length(), OSD_NAME_MAX_LENGTH); 133 byte[] params; 134 try { 135 params = name.substring(0, length).getBytes("US-ASCII"); 136 } catch (UnsupportedEncodingException e) { 137 return null; 138 } 139 return buildCommand(src, dest, HdmiCec.MESSAGE_SET_OSD_NAME, params); 140 } 141 142 /** 143 * Build <Report Physical Address> command. It has two bytes physical 144 * address and one byte device type as parameter. 145 * 146 * <p>This is a broadcast message sent to all devices on the bus. 147 * 148 * @param src source address of command 149 * @param address physical address of device 150 * @param deviceType type of device 151 * @return newly created {@link HdmiCecMessage} 152 */ 153 static HdmiCecMessage buildReportPhysicalAddressCommand(int src, int address, int deviceType) { 154 byte[] params = new byte[] { 155 // Two bytes for physical address 156 (byte) ((address >> 8) & 0xFF), 157 (byte) (address & 0xFF), 158 // One byte device type 159 (byte) deviceType 160 }; 161 // <Report Physical Address> is broadcast message. 162 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS, 163 params); 164 } 165 166 /** 167 * Build <Device Vendor Id> command. It has three bytes vendor id as 168 * parameter. 169 * 170 * <p>This is a broadcast message sent to all devices on the bus. 171 * 172 * @param src source address of command 173 * @param vendorId device's vendor id 174 * @return newly created {@link HdmiCecMessage} 175 */ 176 static HdmiCecMessage buildDeviceVendorIdCommand(int src, int vendorId) { 177 byte[] params = new byte[] { 178 (byte) ((vendorId >> 16) & 0xFF), 179 (byte) ((vendorId >> 8) & 0xFF), 180 (byte) (vendorId & 0xFF) 181 }; 182 // <Device Vendor Id> is broadcast message. 183 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_DEVICE_VENDOR_ID, 184 params); 185 } 186 187 /** 188 * Build <Device Vendor Id> command. It has one byte cec version as parameter. 189 * 190 * @param src source address of command 191 * @param dest destination address of command 192 * @param version version of cec. Use 0x04 for "Version 1.3a" and 0x05 for 193 * "Version 1.4 or 1.4a or 1.4b 194 * @return newly created {@link HdmiCecMessage} 195 */ 196 static HdmiCecMessage buildCecVersion(int src, int dest, int version) { 197 byte[] params = new byte[] { 198 (byte) version 199 }; 200 return buildCommand(src, dest, HdmiCec.MESSAGE_CEC_VERSION, params); 201 } 202 203 /** 204 * Build <Request Arc Initiation> 205 * 206 * @param src source address of command 207 * @param dest destination address of command 208 * @return newly created {@link HdmiCecMessage} 209 */ 210 static HdmiCecMessage buildRequestArcInitiation(int src, int dest) { 211 return buildCommand(src, dest, HdmiCec.MESSAGE_REQUEST_ARC_INITIATION); 212 } 213 214 /** 215 * Build <Request Arc Termination> 216 * 217 * @param src source address of command 218 * @param dest destination address of command 219 * @return newly created {@link HdmiCecMessage} 220 */ 221 static HdmiCecMessage buildRequestArcTermination(int src, int dest) { 222 return buildCommand(src, dest, HdmiCec.MESSAGE_REQUEST_ARC_TERMINATION); 223 } 224 225 /** 226 * Build <Report Arc Initiated> 227 * 228 * @param src source address of command 229 * @param dest destination address of command 230 * @return newly created {@link HdmiCecMessage} 231 */ 232 static HdmiCecMessage buildReportArcInitiated(int src, int dest) { 233 return buildCommand(src, dest, HdmiCec.MESSAGE_REPORT_ARC_INITIATED); 234 } 235 236 /** 237 * Build <Report Arc Terminated> 238 * 239 * @param src source address of command 240 * @param dest destination address of command 241 * @return newly created {@link HdmiCecMessage} 242 */ 243 static HdmiCecMessage buildReportArcTerminated(int src, int dest) { 244 return buildCommand(src, dest, HdmiCec.MESSAGE_REPORT_ARC_TERMINATED); 245 } 246 247 /** 248 * Build <Text View On> command. 249 * 250 * @param src source address of command 251 * @param dest destination address of command 252 * @return newly created {@link HdmiCecMessage} 253 */ 254 static HdmiCecMessage buildTextViewOn(int src, int dest) { 255 return buildCommand(src, dest, HdmiCec.MESSAGE_TEXT_VIEW_ON); 256 } 257 258 /** 259 * Build <Active Source> command. 260 * 261 * @param src source address of command 262 * @param physicalAddress physical address of the device to become active 263 * @return newly created {@link HdmiCecMessage} 264 */ 265 static HdmiCecMessage buildActiveSource(int src, int physicalAddress) { 266 return buildCommand(src, HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_ACTIVE_SOURCE, 267 physicalAddressToParam(physicalAddress)); 268 } 269 270 /** 271 * Build <Give Device Power Status> command. 272 * 273 * @param src source address of command 274 * @param dest destination address of command 275 * @return newly created {@link HdmiCecMessage} 276 */ 277 static HdmiCecMessage buildGiveDevicePowerStatus(int src, int dest) { 278 return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS); 279 } 280 281 /** 282 * Build a {@link HdmiCecMessage} without extra parameter. 283 * 284 * @param src source address of command 285 * @param dest destination address of command 286 * @param opcode opcode for a message 287 * @return newly created {@link HdmiCecMessage} 288 */ 289 private static HdmiCecMessage buildCommand(int src, int dest, int opcode) { 290 return new HdmiCecMessage(src, dest, opcode, HdmiCecMessage.EMPTY_PARAM); 291 } 292 293 /** 294 * Build a {@link HdmiCecMessage} with given values. 295 * 296 * @param src source address of command 297 * @param dest destination address of command 298 * @param opcode opcode for a message 299 * @param params extra parameters for command 300 * @return newly created {@link HdmiCecMessage} 301 */ 302 private static HdmiCecMessage buildCommand(int src, int dest, int opcode, byte[] params) { 303 return new HdmiCecMessage(src, dest, opcode, params); 304 } 305 306 private static byte[] physicalAddressToParam(int physicalAddress) { 307 return new byte[] { 308 (byte) (physicalAddress >> 8), 309 (byte) (physicalAddress & 0xFF) 310 }; 311 } 312} 313