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 java.io.UnsupportedEncodingException;
20 import java.util.Arrays;
21 
22 /**
23  * A helper class to build {@link HdmiCecMessage} from various cec commands.
24  */
25 public class HdmiCecMessageBuilder {
26     private static final int OSD_NAME_MAX_LENGTH = 13;
27 
HdmiCecMessageBuilder()28     private HdmiCecMessageBuilder() {}
29 
30     /**
31      * Build {@link HdmiCecMessage} from raw data.
32      *
33      * @param src source address of command
34      * @param dest destination address of command
35      * @param body body of message. It includes opcode.
36      * @return newly created {@link HdmiCecMessage}
37      */
of(int src, int dest, byte[] body)38     static HdmiCecMessage of(int src, int dest, byte[] body) {
39         byte opcode = body[0];
40         byte params[] = Arrays.copyOfRange(body, 1, body.length);
41         return new HdmiCecMessage(src, dest, opcode, params);
42     }
43 
44     /**
45      * Build <Feature Abort> command. <Feature Abort> consists of
46      * 1 byte original opcode and 1 byte reason fields with basic fields.
47      *
48      * @param src source address of command
49      * @param dest destination address of command
50      * @param originalOpcode original opcode causing feature abort
51      * @param reason reason of feature abort
52      * @return newly created {@link HdmiCecMessage}
53      */
buildFeatureAbortCommand(int src, int dest, int originalOpcode, int reason)54     static HdmiCecMessage buildFeatureAbortCommand(int src, int dest, int originalOpcode,
55             int reason) {
56         byte[] params = new byte[] {
57                 (byte) (originalOpcode & 0xFF),
58                 (byte) (reason & 0xFF),
59         };
60         return buildCommand(src, dest, Constants.MESSAGE_FEATURE_ABORT, params);
61     }
62 
63     /**
64      * Build <Give Physical Address> command.
65      *
66      * @param src source address of command
67      * @param dest destination address of command
68      * @return newly created {@link HdmiCecMessage}
69      */
buildGivePhysicalAddress(int src, int dest)70     static HdmiCecMessage buildGivePhysicalAddress(int src, int dest) {
71         return buildCommand(src, dest, Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS);
72     }
73 
74     /**
75      * Build <Give Osd Name> command.
76      *
77      * @param src source address of command
78      * @param dest destination address of command
79      * @return newly created {@link HdmiCecMessage}
80      */
buildGiveOsdNameCommand(int src, int dest)81     static HdmiCecMessage buildGiveOsdNameCommand(int src, int dest) {
82         return buildCommand(src, dest, Constants.MESSAGE_GIVE_OSD_NAME);
83     }
84 
85     /**
86      * Build <Give Vendor Id Command> command.
87      *
88      * @param src source address of command
89      * @param dest destination address of command
90      * @return newly created {@link HdmiCecMessage}
91      */
buildGiveDeviceVendorIdCommand(int src, int dest)92     static HdmiCecMessage buildGiveDeviceVendorIdCommand(int src, int dest) {
93         return buildCommand(src, dest, Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID);
94     }
95 
96     /**
97      * Build <Set Menu Language > command.
98      *
99      * <p>This is a broadcast message sent to all devices on the bus.
100      *
101      * @param src source address of command
102      * @param language 3-letter ISO639-2 based language code
103      * @return newly created {@link HdmiCecMessage} if language is valid.
104      *         Otherwise, return null
105      */
buildSetMenuLanguageCommand(int src, String language)106     static HdmiCecMessage buildSetMenuLanguageCommand(int src, String language) {
107         if (language.length() != 3) {
108             return null;
109         }
110         // Hdmi CEC uses lower-cased ISO 639-2 (3 letters code).
111         String normalized = language.toLowerCase();
112         byte[] params = new byte[] {
113                 (byte) (normalized.charAt(0) & 0xFF),
114                 (byte) (normalized.charAt(1) & 0xFF),
115                 (byte) (normalized.charAt(2) & 0xFF),
116         };
117         // <Set Menu Language> is broadcast message.
118         return buildCommand(src, Constants.ADDR_BROADCAST,
119                 Constants.MESSAGE_SET_MENU_LANGUAGE, params);
120     }
121 
122     /**
123      * Build &lt;Set Osd Name &gt; command.
124      *
125      * @param src source address of command
126      * @param name display (OSD) name of device
127      * @return newly created {@link HdmiCecMessage} if valid name. Otherwise,
128      *         return null
129      */
buildSetOsdNameCommand(int src, int dest, String name)130     static HdmiCecMessage buildSetOsdNameCommand(int src, int dest, String name) {
131         int length = Math.min(name.length(), OSD_NAME_MAX_LENGTH);
132         byte[] params;
133         try {
134             params = name.substring(0, length).getBytes("US-ASCII");
135         } catch (UnsupportedEncodingException e) {
136             return null;
137         }
138         return buildCommand(src, dest, Constants.MESSAGE_SET_OSD_NAME, params);
139     }
140 
141     /**
142      * Build &lt;Report Physical Address&gt; command. It has two bytes physical
143      * address and one byte device type as parameter.
144      *
145      * <p>This is a broadcast message sent to all devices on the bus.
146      *
147      * @param src source address of command
148      * @param address physical address of device
149      * @param deviceType type of device
150      * @return newly created {@link HdmiCecMessage}
151      */
buildReportPhysicalAddressCommand(int src, int address, int deviceType)152     static HdmiCecMessage buildReportPhysicalAddressCommand(int src, int address, int deviceType) {
153         byte[] params = new byte[] {
154                 // Two bytes for physical address
155                 (byte) ((address >> 8) & 0xFF),
156                 (byte) (address & 0xFF),
157                 // One byte device type
158                 (byte) (deviceType & 0xFF)
159         };
160         // <Report Physical Address> is broadcast message.
161         return buildCommand(src, Constants.ADDR_BROADCAST,
162                 Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS, params);
163     }
164 
165     /**
166      * Build &lt;Device Vendor Id&gt; command. It has three bytes vendor id as
167      * parameter.
168      *
169      * <p>This is a broadcast message sent to all devices on the bus.
170      *
171      * @param src source address of command
172      * @param vendorId device's vendor id
173      * @return newly created {@link HdmiCecMessage}
174      */
buildDeviceVendorIdCommand(int src, int vendorId)175     static HdmiCecMessage buildDeviceVendorIdCommand(int src, int vendorId) {
176         byte[] params = new byte[] {
177                 (byte) ((vendorId >> 16) & 0xFF),
178                 (byte) ((vendorId >> 8) & 0xFF),
179                 (byte) (vendorId & 0xFF)
180         };
181         // <Device Vendor Id> is broadcast message.
182         return buildCommand(src, Constants.ADDR_BROADCAST,
183                 Constants.MESSAGE_DEVICE_VENDOR_ID, params);
184     }
185 
186     /**
187      * Build &lt;Device Vendor Id&gt; command. It has one byte cec version as parameter.
188      *
189      * @param src source address of command
190      * @param dest destination address of command
191      * @param version version of cec. Use 0x04 for "Version 1.3a" and 0x05 for
192      *                "Version 1.4 or 1.4a or 1.4b
193      * @return newly created {@link HdmiCecMessage}
194      */
buildCecVersion(int src, int dest, int version)195     static HdmiCecMessage buildCecVersion(int src, int dest, int version) {
196         byte[] params = new byte[] {
197                 (byte) (version & 0xFF)
198         };
199         return buildCommand(src, dest, Constants.MESSAGE_CEC_VERSION, params);
200     }
201 
202     /**
203      * Build &lt;Request Arc Initiation&gt;
204      *
205      * @param src source address of command
206      * @param dest destination address of command
207      * @return newly created {@link HdmiCecMessage}
208      */
buildRequestArcInitiation(int src, int dest)209     static HdmiCecMessage buildRequestArcInitiation(int src, int dest) {
210         return buildCommand(src, dest, Constants.MESSAGE_REQUEST_ARC_INITIATION);
211     }
212 
213     /**
214      * Build &lt;Request Arc Termination&gt;
215      *
216      * @param src source address of command
217      * @param dest destination address of command
218      * @return newly created {@link HdmiCecMessage}
219      */
buildRequestArcTermination(int src, int dest)220     static HdmiCecMessage buildRequestArcTermination(int src, int dest) {
221         return buildCommand(src, dest, Constants.MESSAGE_REQUEST_ARC_TERMINATION);
222     }
223 
224     /**
225      * Build &lt;Report Arc Initiated&gt;
226      *
227      * @param src source address of command
228      * @param dest destination address of command
229      * @return newly created {@link HdmiCecMessage}
230      */
buildReportArcInitiated(int src, int dest)231     static HdmiCecMessage buildReportArcInitiated(int src, int dest) {
232         return buildCommand(src, dest, Constants.MESSAGE_REPORT_ARC_INITIATED);
233     }
234 
235     /**
236      * Build &lt;Report Arc Terminated&gt;
237      *
238      * @param src source address of command
239      * @param dest destination address of command
240      * @return newly created {@link HdmiCecMessage}
241      */
buildReportArcTerminated(int src, int dest)242     static HdmiCecMessage buildReportArcTerminated(int src, int dest) {
243         return buildCommand(src, dest, Constants.MESSAGE_REPORT_ARC_TERMINATED);
244     }
245 
246     /**
247      * Build &lt;Text View On&gt; command.
248      *
249      * @param src source address of command
250      * @param dest destination address of command
251      * @return newly created {@link HdmiCecMessage}
252      */
buildTextViewOn(int src, int dest)253     static HdmiCecMessage buildTextViewOn(int src, int dest) {
254         return buildCommand(src, dest, Constants.MESSAGE_TEXT_VIEW_ON);
255     }
256 
257     /**
258      * Build &lt;Active Source&gt; command.
259      *
260      * @param src source address of command
261      * @param physicalAddress physical address of the device to become active
262      * @return newly created {@link HdmiCecMessage}
263      */
buildActiveSource(int src, int physicalAddress)264     static HdmiCecMessage buildActiveSource(int src, int physicalAddress) {
265         return buildCommand(src, Constants.ADDR_BROADCAST, Constants.MESSAGE_ACTIVE_SOURCE,
266                 physicalAddressToParam(physicalAddress));
267     }
268 
269     /**
270      * Build &lt;Inactive Source&gt; command.
271      *
272      * @param src source address of command
273      * @param physicalAddress physical address of the device to become inactive
274      * @return newly created {@link HdmiCecMessage}
275      */
buildInactiveSource(int src, int physicalAddress)276     static HdmiCecMessage buildInactiveSource(int src, int physicalAddress) {
277         return buildCommand(src, Constants.ADDR_TV,
278                 Constants.MESSAGE_INACTIVE_SOURCE, physicalAddressToParam(physicalAddress));
279     }
280 
281     /**
282      * Build &lt;Set Stream Path&gt; command.
283      *
284      * <p>This is a broadcast message sent to all devices on the bus.
285      *
286      * @param src source address of command
287      * @param streamPath physical address of the device to start streaming
288      * @return newly created {@link HdmiCecMessage}
289      */
buildSetStreamPath(int src, int streamPath)290     static HdmiCecMessage buildSetStreamPath(int src, int streamPath) {
291         return buildCommand(src, Constants.ADDR_BROADCAST,
292                 Constants.MESSAGE_SET_STREAM_PATH, physicalAddressToParam(streamPath));
293     }
294 
295     /**
296      * Build &lt;Routing Change&gt; command.
297      *
298      * <p>This is a broadcast message sent to all devices on the bus.
299      *
300      * @param src source address of command
301      * @param oldPath physical address of the currently active routing path
302      * @param newPath physical address of the new active routing path
303      * @return newly created {@link HdmiCecMessage}
304      */
buildRoutingChange(int src, int oldPath, int newPath)305     static HdmiCecMessage buildRoutingChange(int src, int oldPath, int newPath) {
306         byte[] param = new byte[] {
307             (byte) ((oldPath >> 8) & 0xFF), (byte) (oldPath & 0xFF),
308             (byte) ((newPath >> 8) & 0xFF), (byte) (newPath & 0xFF)
309         };
310         return buildCommand(src, Constants.ADDR_BROADCAST, Constants.MESSAGE_ROUTING_CHANGE,
311                 param);
312     }
313 
314     /**
315      * Build &lt;Give Device Power Status&gt; command.
316      *
317      * @param src source address of command
318      * @param dest destination address of command
319      * @return newly created {@link HdmiCecMessage}
320      */
buildGiveDevicePowerStatus(int src, int dest)321     static HdmiCecMessage buildGiveDevicePowerStatus(int src, int dest) {
322         return buildCommand(src, dest, Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS);
323     }
324 
325     /**
326      * Build &lt;Report Power Status&gt; command.
327      *
328      * @param src source address of command
329      * @param dest destination address of command
330      * @param powerStatus power status of the device
331      * @return newly created {@link HdmiCecMessage}
332      */
buildReportPowerStatus(int src, int dest, int powerStatus)333     static HdmiCecMessage buildReportPowerStatus(int src, int dest, int powerStatus) {
334         byte[] param = new byte[] {
335                 (byte) (powerStatus & 0xFF)
336         };
337         return buildCommand(src, dest, Constants.MESSAGE_REPORT_POWER_STATUS, param);
338     }
339 
340     /**
341      * Build &lt;Report Menu Status&gt; command.
342      *
343      * @param src source address of command
344      * @param dest destination address of command
345      * @param menuStatus menu status of the device
346      * @return newly created {@link HdmiCecMessage}
347      */
buildReportMenuStatus(int src, int dest, int menuStatus)348     static HdmiCecMessage buildReportMenuStatus(int src, int dest, int menuStatus) {
349         byte[] param = new byte[] {
350                 (byte) (menuStatus & 0xFF)
351         };
352         return buildCommand(src, dest, Constants.MESSAGE_MENU_STATUS, param);
353     }
354 
355     /**
356      * Build &lt;System Audio Mode Request&gt; command.
357      *
358      * @param src source address of command
359      * @param avr destination address of command, it should be AVR
360      * @param avrPhysicalAddress physical address of AVR
361      * @param enableSystemAudio whether to enable System Audio Mode or not
362      * @return newly created {@link HdmiCecMessage}
363      */
buildSystemAudioModeRequest(int src, int avr, int avrPhysicalAddress, boolean enableSystemAudio)364     static HdmiCecMessage buildSystemAudioModeRequest(int src, int avr, int avrPhysicalAddress,
365             boolean enableSystemAudio) {
366         if (enableSystemAudio) {
367             return buildCommand(src, avr, Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST,
368                     physicalAddressToParam(avrPhysicalAddress));
369         } else {
370             return buildCommand(src, avr, Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST);
371         }
372     }
373 
374     /**
375      * Build &lt;Give Audio Status&gt; command.
376      *
377      * @param src source address of command
378      * @param dest destination address of command
379      * @return newly created {@link HdmiCecMessage}
380      */
buildGiveAudioStatus(int src, int dest)381     static HdmiCecMessage buildGiveAudioStatus(int src, int dest) {
382         return buildCommand(src, dest, Constants.MESSAGE_GIVE_AUDIO_STATUS);
383     }
384 
385     /**
386      * Build &lt;User Control Pressed&gt; command.
387      *
388      * @param src source address of command
389      * @param dest destination address of command
390      * @param uiCommand keycode that user pressed
391      * @return newly created {@link HdmiCecMessage}
392      */
buildUserControlPressed(int src, int dest, int uiCommand)393     static HdmiCecMessage buildUserControlPressed(int src, int dest, int uiCommand) {
394         return buildUserControlPressed(src, dest, new byte[] { (byte) (uiCommand & 0xFF) });
395     }
396 
397     /**
398      * Build &lt;User Control Pressed&gt; command.
399      *
400      * @param src source address of command
401      * @param dest destination address of command
402      * @param commandParam uiCommand and the additional parameter
403      * @return newly created {@link HdmiCecMessage}
404      */
buildUserControlPressed(int src, int dest, byte[] commandParam)405     static HdmiCecMessage buildUserControlPressed(int src, int dest, byte[] commandParam) {
406         return buildCommand(src, dest, Constants.MESSAGE_USER_CONTROL_PRESSED, commandParam);
407     }
408 
409     /**
410      * Build &lt;User Control Released&gt; command.
411      *
412      * @param src source address of command
413      * @param dest destination address of command
414      * @return newly created {@link HdmiCecMessage}
415      */
buildUserControlReleased(int src, int dest)416     static HdmiCecMessage buildUserControlReleased(int src, int dest) {
417         return buildCommand(src, dest, Constants.MESSAGE_USER_CONTROL_RELEASED);
418     }
419 
420     /**
421      * Build &lt;Give System Audio Mode Status&gt; command.
422      *
423      * @param src source address of command
424      * @param dest destination address of command
425      * @return newly created {@link HdmiCecMessage}
426      */
buildGiveSystemAudioModeStatus(int src, int dest)427     static HdmiCecMessage buildGiveSystemAudioModeStatus(int src, int dest) {
428         return buildCommand(src, dest, Constants.MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS);
429     }
430 
431     /**
432      * Build &lt;Standby&gt; command.
433      *
434      * @param src source address of command
435      * @param dest destination address of command
436      * @return newly created {@link HdmiCecMessage}
437      */
buildStandby(int src, int dest)438     public static HdmiCecMessage buildStandby(int src, int dest) {
439         return buildCommand(src, dest, Constants.MESSAGE_STANDBY);
440     }
441 
442     /**
443      * Build &lt;Vendor Command&gt; command.
444      *
445      * @param src source address of command
446      * @param dest destination address of command
447      * @param params vendor-specific parameters
448      * @return newly created {@link HdmiCecMessage}
449      */
buildVendorCommand(int src, int dest, byte[] params)450     static HdmiCecMessage buildVendorCommand(int src, int dest, byte[] params) {
451         return buildCommand(src, dest, Constants.MESSAGE_VENDOR_COMMAND, params);
452     }
453 
454     /**
455      * Build &lt;Vendor Command With ID&gt; command.
456      *
457      * @param src source address of command
458      * @param dest destination address of command
459      * @param vendorId vendor ID
460      * @param operands vendor-specific parameters
461      * @return newly created {@link HdmiCecMessage}
462      */
buildVendorCommandWithId(int src, int dest, int vendorId, byte[] operands)463     static HdmiCecMessage buildVendorCommandWithId(int src, int dest, int vendorId,
464             byte[] operands) {
465         byte[] params = new byte[operands.length + 3];  // parameter plus len(vendorId)
466         params[0] = (byte) ((vendorId >> 16) & 0xFF);
467         params[1] = (byte) ((vendorId >> 8) & 0xFF);
468         params[2] = (byte) (vendorId & 0xFF);
469         System.arraycopy(operands, 0, params, 3, operands.length);
470         return buildCommand(src, dest, Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, params);
471     }
472 
473     /**
474      * Build &lt;Record On&gt; command.
475      *
476      * @param src source address of command
477      * @param dest destination address of command
478      * @param params parameter of command
479      * @return newly created {@link HdmiCecMessage}
480      */
buildRecordOn(int src, int dest, byte[] params)481     static HdmiCecMessage buildRecordOn(int src, int dest, byte[] params) {
482         return buildCommand(src, dest, Constants.MESSAGE_RECORD_ON, params);
483     }
484 
485     /**
486      * Build &lt;Record Off&gt; command.
487      *
488      * @param src source address of command
489      * @param dest destination address of command
490      * @return newly created {@link HdmiCecMessage}
491      */
buildRecordOff(int src, int dest)492     static HdmiCecMessage buildRecordOff(int src, int dest) {
493         return buildCommand(src, dest, Constants.MESSAGE_RECORD_OFF);
494     }
495 
496     /**
497      * Build &lt;Set Digital Timer&gt; command.
498      *
499      * @param src source address of command
500      * @param dest destination address of command
501      * @param params byte array of timing information and digital service information to be recorded
502      * @return newly created {@link HdmiCecMessage}
503      */
buildSetDigitalTimer(int src, int dest, byte[] params)504     static HdmiCecMessage buildSetDigitalTimer(int src, int dest, byte[] params) {
505         return buildCommand(src, dest, Constants.MESSAGE_SET_DIGITAL_TIMER, params);
506     }
507 
508     /**
509      * Build &lt;Set Analogue Timer&gt; command.
510      *
511      * @param src source address of command
512      * @param dest destination address of command
513      * @param params byte array of timing information and analog service information to be recorded
514      * @return newly created {@link HdmiCecMessage}
515      */
buildSetAnalogueTimer(int src, int dest, byte[] params)516     static HdmiCecMessage buildSetAnalogueTimer(int src, int dest, byte[] params) {
517         return buildCommand(src, dest, Constants.MESSAGE_SET_ANALOG_TIMER, params);
518     }
519 
520     /**
521      * Build &lt;Set External Timer&gt; command.
522      *
523      * @param src source address of command
524      * @param dest destination address of command
525      * @param params byte array of timing information and external source information to be recorded
526      * @return newly created {@link HdmiCecMessage}
527      */
buildSetExternalTimer(int src, int dest, byte[] params)528     static HdmiCecMessage buildSetExternalTimer(int src, int dest, byte[] params) {
529         return buildCommand(src, dest, Constants.MESSAGE_SET_EXTERNAL_TIMER, params);
530     }
531 
532     /**
533      * Build &lt;Clear Digital Timer&gt; command.
534      *
535      * @param src source address of command
536      * @param dest destination address of command
537      * @param params byte array of timing information and digital service information to be cleared
538      * @return newly created {@link HdmiCecMessage}
539      */
buildClearDigitalTimer(int src, int dest, byte[] params)540     static HdmiCecMessage buildClearDigitalTimer(int src, int dest, byte[] params) {
541         return buildCommand(src, dest, Constants.MESSAGE_CLEAR_DIGITAL_TIMER, params);
542     }
543 
544     /**
545      * Build &lt;Clear Analog Timer&gt; command.
546      *
547      * @param src source address of command
548      * @param dest destination address of command
549      * @param params byte array of timing information and analog service information to be cleared
550      * @return newly created {@link HdmiCecMessage}
551      */
buildClearAnalogueTimer(int src, int dest, byte[] params)552     static HdmiCecMessage buildClearAnalogueTimer(int src, int dest, byte[] params) {
553         return buildCommand(src, dest, Constants.MESSAGE_CLEAR_ANALOG_TIMER, params);
554     }
555 
556     /**
557      * Build &lt;Clear Digital Timer&gt; command.
558      *
559      * @param src source address of command
560      * @param dest destination address of command
561      * @param params byte array of timing information and external source information to be cleared
562      * @return newly created {@link HdmiCecMessage}
563      */
buildClearExternalTimer(int src, int dest, byte[] params)564     static HdmiCecMessage buildClearExternalTimer(int src, int dest, byte[] params) {
565         return buildCommand(src, dest, Constants.MESSAGE_CLEAR_EXTERNAL_TIMER, params);
566     }
567 
568     /***** Please ADD new buildXXX() methods above. ******/
569 
570     /**
571      * Build a {@link HdmiCecMessage} without extra parameter.
572      *
573      * @param src source address of command
574      * @param dest destination address of command
575      * @param opcode opcode for a message
576      * @return newly created {@link HdmiCecMessage}
577      */
buildCommand(int src, int dest, int opcode)578     private static HdmiCecMessage buildCommand(int src, int dest, int opcode) {
579         return new HdmiCecMessage(src, dest, opcode, HdmiCecMessage.EMPTY_PARAM);
580     }
581 
582     /**
583      * Build a {@link HdmiCecMessage} with given values.
584      *
585      * @param src source address of command
586      * @param dest destination address of command
587      * @param opcode opcode for a message
588      * @param params extra parameters for command
589      * @return newly created {@link HdmiCecMessage}
590      */
buildCommand(int src, int dest, int opcode, byte[] params)591     private static HdmiCecMessage buildCommand(int src, int dest, int opcode, byte[] params) {
592         return new HdmiCecMessage(src, dest, opcode, params);
593     }
594 
physicalAddressToParam(int physicalAddress)595     private static byte[] physicalAddressToParam(int physicalAddress) {
596         return new byte[] {
597                 (byte) ((physicalAddress >> 8) & 0xFF),
598                 (byte) (physicalAddress & 0xFF)
599         };
600     }
601 }
602