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 android.hardware.hdmi;
18 
19 import android.annotation.SystemApi;
20 import android.os.Parcel;
21 import android.os.Parcelable;
22 
23 /**
24  * A class to encapsulate device information for HDMI devices including CEC and MHL. In terms of
25  * CEC, this container includes basic information such as logical address, physical address and
26  * device type, and additional information like vendor id and osd name. In terms of MHL device, this
27  * container includes adopter id and device type. Otherwise, it keeps the information of other type
28  * devices for which only port ID, physical address are meaningful.
29  *
30  * @hide
31  */
32 @SystemApi
33 public class HdmiDeviceInfo implements Parcelable {
34 
35     /** TV device type. */
36     public static final int DEVICE_TV = 0;
37 
38     /** Recording device type. */
39     public static final int DEVICE_RECORDER = 1;
40 
41     /** Device type reserved for future usage. */
42     public static final int DEVICE_RESERVED = 2;
43 
44     /** Tuner device type. */
45     public static final int DEVICE_TUNER = 3;
46 
47     /** Playback device type. */
48     public static final int DEVICE_PLAYBACK = 4;
49 
50     /** Audio system device type. */
51     public static final int DEVICE_AUDIO_SYSTEM = 5;
52 
53     /** @hide Pure CEC switch device type. */
54     public static final int DEVICE_PURE_CEC_SWITCH = 6;
55 
56     /** @hide Video processor device type. */
57     public static final int DEVICE_VIDEO_PROCESSOR = 7;
58 
59     // Value indicating the device is not an active source.
60     public static final int DEVICE_INACTIVE = -1;
61 
62     /**
63      * Logical address used to indicate the source comes from internal device. The logical address
64      * of TV(0) is used.
65      */
66     public static final int ADDR_INTERNAL = 0;
67 
68     /**
69      * Physical address used to indicate the source comes from internal device. The physical address
70      * of TV(0) is used.
71      */
72     public static final int PATH_INTERNAL = 0x0000;
73 
74     /** Invalid physical address (routing path) */
75     public static final int PATH_INVALID = 0xFFFF;
76 
77     /** Invalid port ID */
78     public static final int PORT_INVALID = -1;
79 
80     /** Invalid device ID */
81     public static final int ID_INVALID = 0xFFFF;
82 
83     /** Device info used to indicate an inactivated device. */
84     public static final HdmiDeviceInfo INACTIVE_DEVICE = new HdmiDeviceInfo();
85 
86     private static final int HDMI_DEVICE_TYPE_CEC = 0;
87     private static final int HDMI_DEVICE_TYPE_MHL = 1;
88     private static final int HDMI_DEVICE_TYPE_HARDWARE = 2;
89 
90     // Type used to indicate the device that has relinquished its active source status.
91     private static final int HDMI_DEVICE_TYPE_INACTIVE = 100;
92 
93     // Offset used for id value. MHL devices, for instance, will be assigned the value from
94     // ID_OFFSET_MHL.
95     private static final int ID_OFFSET_CEC = 0x0;
96     private static final int ID_OFFSET_MHL = 0x80;
97     private static final int ID_OFFSET_HARDWARE = 0xC0;
98 
99     // Common parameters for all device.
100     private final int mId;
101     private final int mHdmiDeviceType;
102     private final int mPhysicalAddress;
103     private final int mPortId;
104 
105     // CEC only parameters.
106     private final int mLogicalAddress;
107     private final int mDeviceType;
108     private final int mVendorId;
109     private final String mDisplayName;
110     private final int mDevicePowerStatus;
111 
112     // MHL only parameters.
113     private final int mDeviceId;
114     private final int mAdopterId;
115 
116     /**
117      * A helper class to deserialize {@link HdmiDeviceInfo} for a parcel.
118      */
119     public static final Parcelable.Creator<HdmiDeviceInfo> CREATOR =
120             new Parcelable.Creator<HdmiDeviceInfo>() {
121                 @Override
122                 public HdmiDeviceInfo createFromParcel(Parcel source) {
123                     int hdmiDeviceType = source.readInt();
124                     int physicalAddress = source.readInt();
125                     int portId = source.readInt();
126 
127                     switch (hdmiDeviceType) {
128                         case HDMI_DEVICE_TYPE_CEC:
129                             int logicalAddress = source.readInt();
130                             int deviceType = source.readInt();
131                             int vendorId = source.readInt();
132                             int powerStatus = source.readInt();
133                             String displayName = source.readString();
134                             return new HdmiDeviceInfo(logicalAddress, physicalAddress, portId,
135                                     deviceType, vendorId, displayName, powerStatus);
136                         case HDMI_DEVICE_TYPE_MHL:
137                             int deviceId = source.readInt();
138                             int adopterId = source.readInt();
139                             return new HdmiDeviceInfo(physicalAddress, portId, adopterId, deviceId);
140                         case HDMI_DEVICE_TYPE_HARDWARE:
141                             return new HdmiDeviceInfo(physicalAddress, portId);
142                         case HDMI_DEVICE_TYPE_INACTIVE:
143                             return HdmiDeviceInfo.INACTIVE_DEVICE;
144                         default:
145                             return null;
146                     }
147                 }
148 
149                 @Override
150                 public HdmiDeviceInfo[] newArray(int size) {
151                     return new HdmiDeviceInfo[size];
152                 }
153             };
154 
155     /**
156      * Constructor. Used to initialize the instance for CEC device.
157      *
158      * @param logicalAddress logical address of HDMI-CEC device
159      * @param physicalAddress physical address of HDMI-CEC device
160      * @param portId HDMI port ID (1 for HDMI1)
161      * @param deviceType type of device
162      * @param vendorId vendor id of device. Used for vendor specific command.
163      * @param displayName name of device
164      * @param powerStatus device power status
165      * @hide
166      */
HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType, int vendorId, String displayName, int powerStatus)167     public HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType,
168             int vendorId, String displayName, int powerStatus) {
169         mHdmiDeviceType = HDMI_DEVICE_TYPE_CEC;
170         mPhysicalAddress = physicalAddress;
171         mPortId = portId;
172 
173         mId = idForCecDevice(logicalAddress);
174         mLogicalAddress = logicalAddress;
175         mDeviceType = deviceType;
176         mVendorId = vendorId;
177         mDevicePowerStatus = powerStatus;
178         mDisplayName = displayName;
179 
180         mDeviceId = -1;
181         mAdopterId = -1;
182     }
183 
184     /**
185      * Constructor. Used to initialize the instance for CEC device.
186      *
187      * @param logicalAddress logical address of HDMI-CEC device
188      * @param physicalAddress physical address of HDMI-CEC device
189      * @param portId HDMI port ID (1 for HDMI1)
190      * @param deviceType type of device
191      * @param vendorId vendor id of device. Used for vendor specific command.
192      * @param displayName name of device
193      * @hide
194      */
HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType, int vendorId, String displayName)195     public HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType,
196             int vendorId, String displayName) {
197         this(logicalAddress, physicalAddress, portId, deviceType,
198                 vendorId, displayName, HdmiControlManager.POWER_STATUS_UNKNOWN);
199     }
200 
201     /**
202      * Constructor. Used to initialize the instance for device representing hardware port.
203      *
204      * @param physicalAddress physical address of the port
205      * @param portId HDMI port ID (1 for HDMI1)
206      * @hide
207      */
HdmiDeviceInfo(int physicalAddress, int portId)208     public HdmiDeviceInfo(int physicalAddress, int portId) {
209         mHdmiDeviceType = HDMI_DEVICE_TYPE_HARDWARE;
210         mPhysicalAddress = physicalAddress;
211         mPortId = portId;
212 
213         mId = idForHardware(portId);
214         mLogicalAddress = -1;
215         mDeviceType = DEVICE_RESERVED;
216         mVendorId = 0;
217         mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
218         mDisplayName = "HDMI" + portId;
219 
220         mDeviceId = -1;
221         mAdopterId = -1;
222     }
223 
224     /**
225      * Constructor. Used to initialize the instance for MHL device.
226      *
227      * @param physicalAddress physical address of HDMI device
228      * @param portId portId HDMI port ID (1 for HDMI1)
229      * @param adopterId adopter id of MHL
230      * @param deviceId device id of MHL
231      * @hide
232      */
HdmiDeviceInfo(int physicalAddress, int portId, int adopterId, int deviceId)233     public HdmiDeviceInfo(int physicalAddress, int portId, int adopterId, int deviceId) {
234         mHdmiDeviceType = HDMI_DEVICE_TYPE_MHL;
235         mPhysicalAddress = physicalAddress;
236         mPortId = portId;
237 
238         mId = idForMhlDevice(portId);
239         mLogicalAddress = -1;
240         mDeviceType = DEVICE_RESERVED;
241         mVendorId = 0;
242         mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
243         mDisplayName = "Mobile";
244 
245         mDeviceId = adopterId;
246         mAdopterId = deviceId;
247     }
248 
249     /**
250      * Constructor. Used to initialize the instance representing an inactivated device.
251      * Can be passed input change listener to indicate the active source yielded
252      * its status, hence the listener should take an appropriate action such as
253      * switching to other input.
254      */
HdmiDeviceInfo()255     public HdmiDeviceInfo() {
256         mHdmiDeviceType = HDMI_DEVICE_TYPE_INACTIVE;
257         mPhysicalAddress = PATH_INVALID;
258         mId = ID_INVALID;
259 
260         mLogicalAddress = -1;
261         mDeviceType = DEVICE_INACTIVE;
262         mPortId = PORT_INVALID;
263         mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
264         mDisplayName = "Inactive";
265         mVendorId = 0;
266 
267         mDeviceId = -1;
268         mAdopterId = -1;
269     }
270 
271     /**
272      * Returns the id of the device.
273      */
getId()274     public int getId() {
275         return mId;
276     }
277 
278     /**
279      * Returns the id to be used for CEC device.
280      *
281      * @param address logical address of CEC device
282      * @return id for CEC device
283      */
idForCecDevice(int address)284     public static int idForCecDevice(int address) {
285         // The id is generated based on the logical address.
286         return ID_OFFSET_CEC + address;
287     }
288 
289     /**
290      * Returns the id to be used for MHL device.
291      *
292      * @param portId port which the MHL device is connected to
293      * @return id for MHL device
294      */
idForMhlDevice(int portId)295     public static int idForMhlDevice(int portId) {
296         // The id is generated based on the port id since there can be only one MHL device per port.
297         return ID_OFFSET_MHL + portId;
298     }
299 
300     /**
301      * Returns the id to be used for hardware port.
302      *
303      * @param portId port id
304      * @return id for hardware port
305      */
idForHardware(int portId)306     public static int idForHardware(int portId) {
307         return ID_OFFSET_HARDWARE + portId;
308     }
309 
310     /**
311      * Returns the CEC logical address of the device.
312      */
getLogicalAddress()313     public int getLogicalAddress() {
314         return mLogicalAddress;
315     }
316 
317     /**
318      * Returns the physical address of the device.
319      */
getPhysicalAddress()320     public int getPhysicalAddress() {
321         return mPhysicalAddress;
322     }
323 
324     /**
325      * Returns the port ID.
326      */
getPortId()327     public int getPortId() {
328         return mPortId;
329     }
330 
331     /**
332      * Returns CEC type of the device. For more details, refer constants between {@link #DEVICE_TV}
333      * and {@link #DEVICE_INACTIVE}.
334      */
getDeviceType()335     public int getDeviceType() {
336         return mDeviceType;
337     }
338 
339     /**
340      * Returns device's power status. It should be one of the following values.
341      * <ul>
342      * <li>{@link HdmiControlManager#POWER_STATUS_ON}
343      * <li>{@link HdmiControlManager#POWER_STATUS_STANDBY}
344      * <li>{@link HdmiControlManager#POWER_STATUS_TRANSIENT_TO_ON}
345      * <li>{@link HdmiControlManager#POWER_STATUS_TRANSIENT_TO_STANDBY}
346      * <li>{@link HdmiControlManager#POWER_STATUS_UNKNOWN}
347      * </ul>
348      */
getDevicePowerStatus()349     public int getDevicePowerStatus() {
350         return mDevicePowerStatus;
351     }
352 
353     /**
354      * Returns MHL device id. Return -1 for non-MHL device.
355      */
getDeviceId()356     public int getDeviceId() {
357         return mDeviceId;
358     }
359 
360     /**
361      * Returns MHL adopter id. Return -1 for non-MHL device.
362      */
getAdopterId()363     public int getAdopterId() {
364         return mAdopterId;
365     }
366 
367     /**
368      * Returns {@code true} if the device is of a type that can be an input source.
369      */
isSourceType()370     public boolean isSourceType() {
371         if (isCecDevice()) {
372             return mDeviceType == DEVICE_PLAYBACK
373                     || mDeviceType == DEVICE_RECORDER
374                     || mDeviceType == DEVICE_TUNER;
375         } else if (isMhlDevice()) {
376             return true;
377         } else {
378             return false;
379         }
380     }
381 
382     /**
383      * Returns {@code true} if the device represents an HDMI-CEC device. {@code false} if the device
384      * is either MHL or other device.
385      */
isCecDevice()386     public boolean isCecDevice() {
387         return mHdmiDeviceType == HDMI_DEVICE_TYPE_CEC;
388     }
389 
390     /**
391      * Returns {@code true} if the device represents an MHL device. {@code false} if the device is
392      * either CEC or other device.
393      */
isMhlDevice()394     public boolean isMhlDevice() {
395         return mHdmiDeviceType == HDMI_DEVICE_TYPE_MHL;
396     }
397 
398     /**
399      * Return {@code true} if the device represents an inactivated device that relinquishes
400      * its status as active source by &lt;Active Source&gt; (HDMI-CEC) or Content-off (MHL).
401      */
isInactivated()402     public boolean isInactivated() {
403         return mHdmiDeviceType == HDMI_DEVICE_TYPE_INACTIVE;
404     }
405 
406     /**
407      * Returns display (OSD) name of the device.
408      */
getDisplayName()409     public String getDisplayName() {
410         return mDisplayName;
411     }
412 
413     /**
414      * Returns vendor id of the device. Vendor id is used to distinguish devices built by other
415      * manufactures. This is required for vendor-specific command on CEC standard.
416      */
getVendorId()417     public int getVendorId() {
418         return mVendorId;
419     }
420 
421     /**
422      * Describes the kinds of special objects contained in this Parcelable's marshalled
423      * representation.
424      */
425     @Override
describeContents()426     public int describeContents() {
427         return 0;
428     }
429 
430     /**
431      * Serializes this object into a {@link Parcel}.
432      *
433      * @param dest The Parcel in which the object should be written.
434      * @param flags Additional flags about how the object should be written. May be 0 or
435      *            {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE}.
436      */
437     @Override
writeToParcel(Parcel dest, int flags)438     public void writeToParcel(Parcel dest, int flags) {
439         dest.writeInt(mHdmiDeviceType);
440         dest.writeInt(mPhysicalAddress);
441         dest.writeInt(mPortId);
442         switch (mHdmiDeviceType) {
443             case HDMI_DEVICE_TYPE_CEC:
444                 dest.writeInt(mLogicalAddress);
445                 dest.writeInt(mDeviceType);
446                 dest.writeInt(mVendorId);
447                 dest.writeInt(mDevicePowerStatus);
448                 dest.writeString(mDisplayName);
449                 break;
450             case HDMI_DEVICE_TYPE_MHL:
451                 dest.writeInt(mDeviceId);
452                 dest.writeInt(mAdopterId);
453                 break;
454             case HDMI_DEVICE_TYPE_INACTIVE:
455                 // flow through
456             default:
457                 // no-op
458         }
459     }
460 
461     @Override
toString()462     public String toString() {
463         StringBuffer s = new StringBuffer();
464         switch (mHdmiDeviceType) {
465             case HDMI_DEVICE_TYPE_CEC:
466                 s.append("CEC: ");
467                 s.append("logical_address: ").append(String.format("0x%02X", mLogicalAddress));
468                 s.append(" ");
469                 s.append("device_type: ").append(mDeviceType).append(" ");
470                 s.append("vendor_id: ").append(mVendorId).append(" ");
471                 s.append("display_name: ").append(mDisplayName).append(" ");
472                 s.append("power_status: ").append(mDevicePowerStatus).append(" ");
473                 break;
474             case HDMI_DEVICE_TYPE_MHL:
475                 s.append("MHL: ");
476                 s.append("device_id: ").append(String.format("0x%04X", mDeviceId)).append(" ");
477                 s.append("adopter_id: ").append(String.format("0x%04X", mAdopterId)).append(" ");
478                 break;
479 
480             case HDMI_DEVICE_TYPE_HARDWARE:
481                 s.append("Hardware: ");
482                 break;
483             case HDMI_DEVICE_TYPE_INACTIVE:
484                 s.append("Inactivated: ");
485                 break;
486             default:
487                 return "";
488         }
489         s.append("physical_address: ").append(String.format("0x%04X", mPhysicalAddress));
490         s.append(" ");
491         s.append("port_id: ").append(mPortId);
492         return s.toString();
493     }
494 
495     @Override
equals(Object obj)496     public boolean equals(Object obj) {
497         if (!(obj instanceof HdmiDeviceInfo)) {
498             return false;
499         }
500 
501         HdmiDeviceInfo other = (HdmiDeviceInfo) obj;
502         return mHdmiDeviceType == other.mHdmiDeviceType
503                 && mPhysicalAddress == other.mPhysicalAddress
504                 && mPortId == other.mPortId
505                 && mLogicalAddress == other.mLogicalAddress
506                 && mDeviceType == other.mDeviceType
507                 && mVendorId == other.mVendorId
508                 && mDevicePowerStatus == other.mDevicePowerStatus
509                 && mDisplayName.equals(other.mDisplayName)
510                 && mDeviceId == other.mDeviceId
511                 && mAdopterId == other.mAdopterId;
512     }
513 }
514