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             for (byte data : mParams) {
119                 s.append(String.format(":%02X", data));
120             }
121         }
122         return s.toString();
123     }
124 
opcodeToString(int opcode)125     private static String opcodeToString(int opcode) {
126         switch (opcode) {
127             case Constants.MESSAGE_FEATURE_ABORT:
128                 return "Feature Abort";
129             case Constants.MESSAGE_IMAGE_VIEW_ON:
130                 return "Image View On";
131             case Constants.MESSAGE_TUNER_STEP_INCREMENT:
132                 return "Tuner Step Increment";
133             case Constants.MESSAGE_TUNER_STEP_DECREMENT:
134                 return "Tuner Step Decrement";
135             case Constants.MESSAGE_TUNER_DEVICE_STATUS:
136                 return "Tuner Device Status";
137             case Constants.MESSAGE_GIVE_TUNER_DEVICE_STATUS:
138                 return "Give Tuner Device Status";
139             case Constants.MESSAGE_RECORD_ON:
140                 return "Record On";
141             case Constants.MESSAGE_RECORD_STATUS:
142                 return "Record Status";
143             case Constants.MESSAGE_RECORD_OFF:
144                 return "Record Off";
145             case Constants.MESSAGE_TEXT_VIEW_ON:
146                 return "Text View On";
147             case Constants.MESSAGE_RECORD_TV_SCREEN:
148                 return "Record Tv Screen";
149             case Constants.MESSAGE_GIVE_DECK_STATUS:
150                 return "Give Deck Status";
151             case Constants.MESSAGE_DECK_STATUS:
152                 return "Deck Status";
153             case Constants.MESSAGE_SET_MENU_LANGUAGE:
154                 return "Set Menu Language";
155             case Constants.MESSAGE_CLEAR_ANALOG_TIMER:
156                 return "Clear Analog Timer";
157             case Constants.MESSAGE_SET_ANALOG_TIMER:
158                 return "Set Analog Timer";
159             case Constants.MESSAGE_TIMER_STATUS:
160                 return "Timer Status";
161             case Constants.MESSAGE_STANDBY:
162                 return "Standby";
163             case Constants.MESSAGE_PLAY:
164                 return "Play";
165             case Constants.MESSAGE_DECK_CONTROL:
166                 return "Deck Control";
167             case Constants.MESSAGE_TIMER_CLEARED_STATUS:
168                 return "Timer Cleared Status";
169             case Constants.MESSAGE_USER_CONTROL_PRESSED:
170                 return "User Control Pressed";
171             case Constants.MESSAGE_USER_CONTROL_RELEASED:
172                 return "User Control Release";
173             case Constants.MESSAGE_GIVE_OSD_NAME:
174                 return "Give Osd Name";
175             case Constants.MESSAGE_SET_OSD_NAME:
176                 return "Set Osd Name";
177             case Constants.MESSAGE_SET_OSD_STRING:
178                 return "Set Osd String";
179             case Constants.MESSAGE_SET_TIMER_PROGRAM_TITLE:
180                 return "Set Timer Program Title";
181             case Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST:
182                 return "System Audio Mode Request";
183             case Constants.MESSAGE_GIVE_AUDIO_STATUS:
184                 return "Give Audio Status";
185             case Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE:
186                 return "Set System Audio Mode";
187             case Constants.MESSAGE_REPORT_AUDIO_STATUS:
188                 return "Report Audio Status";
189             case Constants.MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS:
190                 return "Give System Audio Mode Status";
191             case Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS:
192                 return "System Audio Mode Status";
193             case Constants.MESSAGE_ROUTING_CHANGE:
194                 return "Routing Change";
195             case Constants.MESSAGE_ROUTING_INFORMATION:
196                 return "Routing Information";
197             case Constants.MESSAGE_ACTIVE_SOURCE:
198                 return "Active Source";
199             case Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS:
200                 return "Give Physical Address";
201             case Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS:
202                 return "Report Physical Address";
203             case Constants.MESSAGE_REQUEST_ACTIVE_SOURCE:
204                 return "Request Active Source";
205             case Constants.MESSAGE_SET_STREAM_PATH:
206                 return "Set Stream Path";
207             case Constants.MESSAGE_DEVICE_VENDOR_ID:
208                 return "Device Vendor Id";
209             case Constants.MESSAGE_VENDOR_COMMAND:
210                 return "Vendor Command";
211             case Constants.MESSAGE_VENDOR_REMOTE_BUTTON_DOWN:
212                 return "Vendor Remote Button Down";
213             case Constants.MESSAGE_VENDOR_REMOTE_BUTTON_UP:
214                 return "Vendor Remote Button Up";
215             case Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID:
216                 return "Give Device Vendor Id";
217             case Constants.MESSAGE_MENU_REQUEST:
218                 return "Menu Request";
219             case Constants.MESSAGE_MENU_STATUS:
220                 return "Menu Status";
221             case Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS:
222                 return "Give Device Power Status";
223             case Constants.MESSAGE_REPORT_POWER_STATUS:
224                 return "Report Power Status";
225             case Constants.MESSAGE_GET_MENU_LANGUAGE:
226                 return "Get Menu Language";
227             case Constants.MESSAGE_SELECT_ANALOG_SERVICE:
228                 return "Select Analog Service";
229             case Constants.MESSAGE_SELECT_DIGITAL_SERVICE:
230                 return "Select Digital Service";
231             case Constants.MESSAGE_SET_DIGITAL_TIMER:
232                 return "Set Digital Timer";
233             case Constants.MESSAGE_CLEAR_DIGITAL_TIMER:
234                 return "Clear Digital Timer";
235             case Constants.MESSAGE_SET_AUDIO_RATE:
236                 return "Set Audio Rate";
237             case Constants.MESSAGE_INACTIVE_SOURCE:
238                 return "InActive Source";
239             case Constants.MESSAGE_CEC_VERSION:
240                 return "Cec Version";
241             case Constants.MESSAGE_GET_CEC_VERSION:
242                 return "Get Cec Version";
243             case Constants.MESSAGE_VENDOR_COMMAND_WITH_ID:
244                 return "Vendor Command With Id";
245             case Constants.MESSAGE_CLEAR_EXTERNAL_TIMER:
246                 return "Clear External Timer";
247             case Constants.MESSAGE_SET_EXTERNAL_TIMER:
248                 return "Set External Timer";
249             case Constants.MESSAGE_REPORT_SHORT_AUDIO_DESCRIPTOR:
250                 return "Report Short Audio Descriptor";
251             case Constants.MESSAGE_REQUEST_SHORT_AUDIO_DESCRIPTOR:
252                 return "Request Short Audio Descriptor";
253             case Constants.MESSAGE_INITIATE_ARC:
254                 return "Initiate ARC";
255             case Constants.MESSAGE_REPORT_ARC_INITIATED:
256                 return "Report ARC Initiated";
257             case Constants.MESSAGE_REPORT_ARC_TERMINATED:
258                 return "Report ARC Terminated";
259             case Constants.MESSAGE_REQUEST_ARC_INITIATION:
260                 return "Request ARC Initiation";
261             case Constants.MESSAGE_REQUEST_ARC_TERMINATION:
262                 return "Request ARC Termination";
263             case Constants.MESSAGE_TERMINATE_ARC:
264                 return "Terminate ARC";
265             case Constants.MESSAGE_CDC_MESSAGE:
266                 return "Cdc Message";
267             case Constants.MESSAGE_ABORT:
268                 return "Abort";
269             default:
270                 return String.format("Opcode: %02X", opcode);
271         }
272     }
273 }
274 
275