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.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.hardware.hdmi.HdmiControlManager.HdmiCecVersion;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 
26 /**
27  * A class to encapsulate device information for HDMI devices including CEC and MHL. In terms of
28  * CEC, this container includes basic information such as logical address, physical address and
29  * device type, and additional information like vendor id and osd name. In terms of MHL device, this
30  * container includes adopter id and device type. Otherwise, it keeps the information of other type
31  * devices for which only port ID, physical address are meaningful.
32  *
33  * @hide
34  */
35 @SystemApi
36 public class HdmiDeviceInfo implements Parcelable {
37 
38     /** TV device type. */
39     public static final int DEVICE_TV = 0;
40 
41     /** Recording device type. */
42     public static final int DEVICE_RECORDER = 1;
43 
44     /** Device type reserved for future usage. */
45     public static final int DEVICE_RESERVED = 2;
46 
47     /** Tuner device type. */
48     public static final int DEVICE_TUNER = 3;
49 
50     /** Playback device type. */
51     public static final int DEVICE_PLAYBACK = 4;
52 
53     /** Audio system device type. */
54     public static final int DEVICE_AUDIO_SYSTEM = 5;
55 
56     /** @hide Pure CEC switch device type. */
57     public static final int DEVICE_PURE_CEC_SWITCH = 6;
58 
59     /** @hide Video processor device type. */
60     public static final int DEVICE_VIDEO_PROCESSOR = 7;
61 
62     // Value indicating the device is not an active source.
63     public static final int DEVICE_INACTIVE = -1;
64 
65     /**
66      * Logical address used to indicate the source comes from internal device. The logical address
67      * of TV(0) is used.
68      */
69     public static final int ADDR_INTERNAL = 0;
70 
71     /** Invalid or uninitialized logical address */
72     public static final int ADDR_INVALID = -1;
73 
74     /**
75      * Physical address used to indicate the source comes from internal device. The physical address
76      * of TV(0) is used.
77      */
78     public static final int PATH_INTERNAL = 0x0000;
79 
80     /** Invalid physical address (routing path) */
81     public static final int PATH_INVALID = 0xFFFF;
82 
83     /** Invalid port ID */
84     public static final int PORT_INVALID = -1;
85 
86     /** Invalid device ID */
87     public static final int ID_INVALID = 0xFFFF;
88 
89     /** Unknown vendor ID */
90     public static final int VENDOR_ID_UNKNOWN = 0xFFFFFF;
91 
92     /**
93      * Instance that represents an inactive device.
94      * Can be passed to an input change listener to indicate that the active source
95      * yielded its status, allowing the listener to take an appropriate action such as
96      * switching to another input.
97      */
98     public static final HdmiDeviceInfo INACTIVE_DEVICE = new HdmiDeviceInfo();
99 
100     private static final int HDMI_DEVICE_TYPE_CEC = 0;
101     private static final int HDMI_DEVICE_TYPE_MHL = 1;
102     private static final int HDMI_DEVICE_TYPE_HARDWARE = 2;
103 
104     // Type used to indicate the device that has relinquished its active source status.
105     private static final int HDMI_DEVICE_TYPE_INACTIVE = 100;
106 
107     // Offset used for id value. MHL devices, for instance, will be assigned the value from
108     // ID_OFFSET_MHL.
109     private static final int ID_OFFSET_CEC = 0x0;
110     private static final int ID_OFFSET_MHL = 0x80;
111     private static final int ID_OFFSET_HARDWARE = 0xC0;
112 
113     // Common parameters for all device.
114     private final int mId;
115     private final int mHdmiDeviceType;
116     private final int mPhysicalAddress;
117     private final int mPortId;
118 
119     // CEC only parameters.
120     private final int mLogicalAddress;
121     private final int mDeviceType;
122     @HdmiCecVersion
123     private final int mCecVersion;
124     private final int mVendorId;
125     private final String mDisplayName;
126     private final int mDevicePowerStatus;
127     private final DeviceFeatures mDeviceFeatures;
128 
129     // MHL only parameters.
130     private final int mDeviceId;
131     private final int mAdopterId;
132 
133     /**
134      * A helper class to deserialize {@link HdmiDeviceInfo} for a parcel.
135      */
136     public static final @android.annotation.NonNull Parcelable.Creator<HdmiDeviceInfo> CREATOR =
137             new Parcelable.Creator<HdmiDeviceInfo>() {
138                 @Override
139                 public HdmiDeviceInfo createFromParcel(Parcel source) {
140                     int hdmiDeviceType = source.readInt();
141                     int physicalAddress = source.readInt();
142                     int portId = source.readInt();
143 
144                     switch (hdmiDeviceType) {
145                         case HDMI_DEVICE_TYPE_CEC:
146                             int logicalAddress = source.readInt();
147                             int deviceType = source.readInt();
148                             int vendorId = source.readInt();
149                             int powerStatus = source.readInt();
150                             String displayName = source.readString();
151                             int cecVersion = source.readInt();
152                             return cecDeviceBuilder()
153                                     .setLogicalAddress(logicalAddress)
154                                     .setPhysicalAddress(physicalAddress)
155                                     .setPortId(portId)
156                                     .setDeviceType(deviceType)
157                                     .setVendorId(vendorId)
158                                     .setDisplayName(displayName)
159                                     .setDevicePowerStatus(powerStatus)
160                                     .setCecVersion(cecVersion)
161                                     .build();
162                         case HDMI_DEVICE_TYPE_MHL:
163                             int deviceId = source.readInt();
164                             int adopterId = source.readInt();
165                             return mhlDevice(physicalAddress, portId, adopterId, deviceId);
166                         case HDMI_DEVICE_TYPE_HARDWARE:
167                             return hardwarePort(physicalAddress, portId);
168                         case HDMI_DEVICE_TYPE_INACTIVE:
169                             return HdmiDeviceInfo.INACTIVE_DEVICE;
170                         default:
171                             return null;
172                     }
173                 }
174 
175                 @Override
176                 public HdmiDeviceInfo[] newArray(int size) {
177                     return new HdmiDeviceInfo[size];
178                 }
179             };
180 
181     /**
182      * Constructor. Initializes the instance representing an inactive device.
183      * Can be passed to an input change listener to indicate that the active source
184      * yielded its status, allowing the listener to take an appropriate action such as
185      * switching to another input.
186      *
187      * @deprecated Use {@link #INACTIVE_DEVICE} instead.
188      */
189     @Deprecated
HdmiDeviceInfo()190     public HdmiDeviceInfo() {
191         mHdmiDeviceType = HDMI_DEVICE_TYPE_INACTIVE;
192         mPhysicalAddress = PATH_INVALID;
193         mId = ID_INVALID;
194 
195         mLogicalAddress = ADDR_INVALID;
196         mDeviceType = DEVICE_INACTIVE;
197         mCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
198         mPortId = PORT_INVALID;
199         mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
200         mDisplayName = "Inactive";
201         mVendorId = 0;
202         mDeviceFeatures = DeviceFeatures.ALL_FEATURES_SUPPORT_UNKNOWN;
203 
204         mDeviceId = -1;
205         mAdopterId = -1;
206     }
207 
208     /**
209      * Converts an instance to a builder.
210      *
211      * @hide
212      */
toBuilder()213     public Builder toBuilder() {
214         return new Builder(this);
215     }
216 
HdmiDeviceInfo(Builder builder)217     private HdmiDeviceInfo(Builder builder) {
218         this.mHdmiDeviceType = builder.mHdmiDeviceType;
219         this.mPhysicalAddress = builder.mPhysicalAddress;
220         this.mPortId = builder.mPortId;
221         this.mLogicalAddress = builder.mLogicalAddress;
222         this.mDeviceType = builder.mDeviceType;
223         this.mCecVersion = builder.mCecVersion;
224         this.mVendorId = builder.mVendorId;
225         this.mDisplayName = builder.mDisplayName;
226         this.mDevicePowerStatus = builder.mDevicePowerStatus;
227         this.mDeviceFeatures = builder.mDeviceFeatures;
228         this.mDeviceId = builder.mDeviceId;
229         this.mAdopterId = builder.mAdopterId;
230 
231         switch (mHdmiDeviceType) {
232             case HDMI_DEVICE_TYPE_MHL:
233                 this.mId = idForMhlDevice(mPortId);
234                 break;
235             case HDMI_DEVICE_TYPE_HARDWARE:
236                 this.mId = idForHardware(mPortId);
237                 break;
238             case HDMI_DEVICE_TYPE_CEC:
239                 this.mId = idForCecDevice(mLogicalAddress);
240                 break;
241             case HDMI_DEVICE_TYPE_INACTIVE:
242             default:
243                 this.mId = ID_INVALID;
244         }
245     }
246 
247     /**
248      * Creates a Builder for an {@link HdmiDeviceInfo} representing a CEC device.
249      *
250      * @hide
251      */
cecDeviceBuilder()252     public static Builder cecDeviceBuilder() {
253         return new Builder(HDMI_DEVICE_TYPE_CEC);
254     }
255 
256     /**
257      * Creates an {@link HdmiDeviceInfo} representing an MHL device.
258      *
259      * @param physicalAddress physical address of HDMI device
260      * @param portId portId HDMI port ID (1 for HDMI1)
261      * @param adopterId adopter id of MHL
262      * @param deviceId device id of MHL
263      * @hide
264      */
mhlDevice( int physicalAddress, int portId, int adopterId, int deviceId)265     public static HdmiDeviceInfo mhlDevice(
266             int physicalAddress, int portId, int adopterId, int deviceId) {
267         return new Builder(HDMI_DEVICE_TYPE_MHL)
268                 .setPhysicalAddress(physicalAddress)
269                 .setPortId(portId)
270                 .setVendorId(0)
271                 .setDisplayName("Mobile")
272                 .setDeviceId(adopterId)
273                 .setAdopterId(deviceId)
274                 .build();
275     }
276 
277     /**
278      * Creates an {@link HdmiDeviceInfo} representing a hardware port.
279      *
280      * @param physicalAddress physical address of the port
281      * @param portId HDMI port ID (1 for HDMI1)
282      * @hide
283      */
hardwarePort(int physicalAddress, int portId)284     public static HdmiDeviceInfo hardwarePort(int physicalAddress, int portId) {
285         return new Builder(HDMI_DEVICE_TYPE_HARDWARE)
286                 .setPhysicalAddress(physicalAddress)
287                 .setPortId(portId)
288                 .setVendorId(0)
289                 .setDisplayName("HDMI" + portId)
290                 .build();
291     }
292 
293     /**
294      * Returns the id of the device.
295      */
getId()296     public int getId() {
297         return mId;
298     }
299 
300     /**
301      * Returns the CEC features that this device supports.
302      *
303      * @hide
304      */
getDeviceFeatures()305     public DeviceFeatures getDeviceFeatures() {
306         return mDeviceFeatures;
307     }
308 
309     /**
310      * Returns the id to be used for CEC device.
311      *
312      * @param address logical address of CEC device
313      * @return id for CEC device
314      */
idForCecDevice(int address)315     public static int idForCecDevice(int address) {
316         // The id is generated based on the logical address.
317         return ID_OFFSET_CEC + address;
318     }
319 
320     /**
321      * Returns the id to be used for MHL device.
322      *
323      * @param portId port which the MHL device is connected to
324      * @return id for MHL device
325      */
idForMhlDevice(int portId)326     public static int idForMhlDevice(int portId) {
327         // The id is generated based on the port id since there can be only one MHL device per port.
328         return ID_OFFSET_MHL + portId;
329     }
330 
331     /**
332      * Returns the id to be used for hardware port.
333      *
334      * @param portId port id
335      * @return id for hardware port
336      */
idForHardware(int portId)337     public static int idForHardware(int portId) {
338         return ID_OFFSET_HARDWARE + portId;
339     }
340 
341     /**
342      * Returns the CEC logical address of the device.
343      */
getLogicalAddress()344     public int getLogicalAddress() {
345         return mLogicalAddress;
346     }
347 
348     /**
349      * Returns the physical address of the device.
350      */
getPhysicalAddress()351     public int getPhysicalAddress() {
352         return mPhysicalAddress;
353     }
354 
355     /**
356      * Returns the port ID.
357      */
getPortId()358     public int getPortId() {
359         return mPortId;
360     }
361 
362     /**
363      * Returns CEC type of the device. For more details, refer constants between {@link #DEVICE_TV}
364      * and {@link #DEVICE_INACTIVE}.
365      */
getDeviceType()366     public int getDeviceType() {
367         return mDeviceType;
368     }
369 
370     /**
371      * Returns the CEC version the device supports.
372      *
373      * @hide
374      */
375     @HdmiCecVersion
getCecVersion()376     public int getCecVersion() {
377         return mCecVersion;
378     }
379 
380     /**
381      * Returns device's power status. It should be one of the following values.
382      * <ul>
383      * <li>{@link HdmiControlManager#POWER_STATUS_ON}
384      * <li>{@link HdmiControlManager#POWER_STATUS_STANDBY}
385      * <li>{@link HdmiControlManager#POWER_STATUS_TRANSIENT_TO_ON}
386      * <li>{@link HdmiControlManager#POWER_STATUS_TRANSIENT_TO_STANDBY}
387      * <li>{@link HdmiControlManager#POWER_STATUS_UNKNOWN}
388      * </ul>
389      */
getDevicePowerStatus()390     public int getDevicePowerStatus() {
391         return mDevicePowerStatus;
392     }
393 
394     /**
395      * Returns MHL device id. Return -1 for non-MHL device.
396      */
getDeviceId()397     public int getDeviceId() {
398         return mDeviceId;
399     }
400 
401     /**
402      * Returns MHL adopter id. Return -1 for non-MHL device.
403      */
getAdopterId()404     public int getAdopterId() {
405         return mAdopterId;
406     }
407 
408     /**
409      * Returns {@code true} if the device is of a type that can be an input source.
410      */
isSourceType()411     public boolean isSourceType() {
412         if (isCecDevice()) {
413             return mDeviceType == DEVICE_PLAYBACK
414                     || mDeviceType == DEVICE_RECORDER
415                     || mDeviceType == DEVICE_TUNER;
416         } else if (isMhlDevice()) {
417             return true;
418         } else {
419             return false;
420         }
421     }
422 
423     /**
424      * Returns {@code true} if the device represents an HDMI-CEC device. {@code false} if the device
425      * is either MHL or other device.
426      */
isCecDevice()427     public boolean isCecDevice() {
428         return mHdmiDeviceType == HDMI_DEVICE_TYPE_CEC;
429     }
430 
431     /**
432      * Returns {@code true} if the device represents an MHL device. {@code false} if the device is
433      * either CEC or other device.
434      */
isMhlDevice()435     public boolean isMhlDevice() {
436         return mHdmiDeviceType == HDMI_DEVICE_TYPE_MHL;
437     }
438 
439     /**
440      * Return {@code true} if the device represents an inactivated device that relinquishes
441      * its status as active source by &lt;Active Source&gt; (HDMI-CEC) or Content-off (MHL).
442      */
isInactivated()443     public boolean isInactivated() {
444         return mHdmiDeviceType == HDMI_DEVICE_TYPE_INACTIVE;
445     }
446 
447     /**
448      * Returns display (OSD) name of the device.
449      */
getDisplayName()450     public String getDisplayName() {
451         return mDisplayName;
452     }
453 
454     /**
455      * Returns vendor id of the device. Vendor id is used to distinguish devices built by other
456      * manufactures. This is required for vendor-specific command on CEC standard.
457      */
getVendorId()458     public int getVendorId() {
459         return mVendorId;
460     }
461 
462     /**
463      * Describes the kinds of special objects contained in this Parcelable's marshalled
464      * representation.
465      */
466     @Override
describeContents()467     public int describeContents() {
468         return 0;
469     }
470 
471     /**
472      * Serializes this object into a {@link Parcel}.
473      *
474      * @param dest The Parcel in which the object should be written.
475      * @param flags Additional flags about how the object should be written. May be 0 or
476      *            {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE}.
477      */
478     @Override
writeToParcel(Parcel dest, int flags)479     public void writeToParcel(Parcel dest, int flags) {
480         dest.writeInt(mHdmiDeviceType);
481         dest.writeInt(mPhysicalAddress);
482         dest.writeInt(mPortId);
483         switch (mHdmiDeviceType) {
484             case HDMI_DEVICE_TYPE_CEC:
485                 dest.writeInt(mLogicalAddress);
486                 dest.writeInt(mDeviceType);
487                 dest.writeInt(mVendorId);
488                 dest.writeInt(mDevicePowerStatus);
489                 dest.writeString(mDisplayName);
490                 dest.writeInt(mCecVersion);
491                 break;
492             case HDMI_DEVICE_TYPE_MHL:
493                 dest.writeInt(mDeviceId);
494                 dest.writeInt(mAdopterId);
495                 break;
496             case HDMI_DEVICE_TYPE_INACTIVE:
497                 // flow through
498             default:
499                 // no-op
500         }
501     }
502 
503     @NonNull
504     @Override
toString()505     public String toString() {
506         StringBuilder s = new StringBuilder();
507         switch (mHdmiDeviceType) {
508             case HDMI_DEVICE_TYPE_CEC:
509                 s.append("CEC: ");
510                 s.append("logical_address: ").append(String.format("0x%02X", mLogicalAddress));
511                 s.append(" ");
512                 s.append("device_type: ").append(mDeviceType).append(" ");
513                 s.append("cec_version: ").append(mCecVersion).append(" ");
514                 s.append("vendor_id: ").append(mVendorId).append(" ");
515                 s.append("display_name: ").append(mDisplayName).append(" ");
516                 s.append("power_status: ").append(mDevicePowerStatus).append(" ");
517                 break;
518             case HDMI_DEVICE_TYPE_MHL:
519                 s.append("MHL: ");
520                 s.append("device_id: ").append(String.format("0x%04X", mDeviceId)).append(" ");
521                 s.append("adopter_id: ").append(String.format("0x%04X", mAdopterId)).append(" ");
522                 break;
523 
524             case HDMI_DEVICE_TYPE_HARDWARE:
525                 s.append("Hardware: ");
526                 break;
527             case HDMI_DEVICE_TYPE_INACTIVE:
528                 s.append("Inactivated: ");
529                 break;
530             default:
531                 return "";
532         }
533         s.append("physical_address: ").append(String.format("0x%04X", mPhysicalAddress));
534         s.append(" ");
535         s.append("port_id: ").append(mPortId);
536 
537         if (mHdmiDeviceType == HDMI_DEVICE_TYPE_CEC) {
538             s.append("\n  ").append(mDeviceFeatures.toString());
539         }
540 
541         return s.toString();
542     }
543 
544     @Override
equals(@ullable Object obj)545     public boolean equals(@Nullable Object obj) {
546         if (!(obj instanceof HdmiDeviceInfo)) {
547             return false;
548         }
549 
550         HdmiDeviceInfo other = (HdmiDeviceInfo) obj;
551         return mHdmiDeviceType == other.mHdmiDeviceType
552                 && mPhysicalAddress == other.mPhysicalAddress
553                 && mPortId == other.mPortId
554                 && mLogicalAddress == other.mLogicalAddress
555                 && mDeviceType == other.mDeviceType
556                 && mCecVersion == other.mCecVersion
557                 && mVendorId == other.mVendorId
558                 && mDevicePowerStatus == other.mDevicePowerStatus
559                 && mDisplayName.equals(other.mDisplayName)
560                 && mDeviceId == other.mDeviceId
561                 && mAdopterId == other.mAdopterId;
562     }
563 
564     @Override
hashCode()565     public int hashCode() {
566         return java.util.Objects.hash(
567                 mHdmiDeviceType,
568                 mPhysicalAddress,
569                 mPortId,
570                 mLogicalAddress,
571                 mDeviceType,
572                 mCecVersion,
573                 mVendorId,
574                 mDevicePowerStatus,
575                 mDisplayName,
576                 mDeviceId,
577                 mAdopterId);
578     }
579 
580     /**
581      * Builder for {@link HdmiDeviceInfo} instances.
582      *
583      * @hide
584      */
585     public static final class Builder {
586         // Required parameters
587         private final int mHdmiDeviceType;
588 
589         // Common parameters
590         private int mPhysicalAddress = PATH_INVALID;
591         private int mPortId = PORT_INVALID;
592 
593         // CEC parameters
594         private int mLogicalAddress = ADDR_INVALID;
595         private int mDeviceType = DEVICE_RESERVED;
596         @HdmiCecVersion
597         private int mCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
598         private int mVendorId = VENDOR_ID_UNKNOWN;
599         private String mDisplayName = "";
600         private int mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
601         private DeviceFeatures mDeviceFeatures;
602 
603         // MHL parameters
604         private int mDeviceId = -1;
605         private int mAdopterId = -1;
606 
Builder(int hdmiDeviceType)607         private Builder(int hdmiDeviceType) {
608             mHdmiDeviceType = hdmiDeviceType;
609             if (hdmiDeviceType == HDMI_DEVICE_TYPE_CEC) {
610                 mDeviceFeatures = DeviceFeatures.ALL_FEATURES_SUPPORT_UNKNOWN;
611             } else {
612                 mDeviceFeatures = DeviceFeatures.NO_FEATURES_SUPPORTED;
613             }
614         }
615 
Builder(@onNull HdmiDeviceInfo hdmiDeviceInfo)616         private Builder(@NonNull HdmiDeviceInfo hdmiDeviceInfo) {
617             mHdmiDeviceType = hdmiDeviceInfo.mHdmiDeviceType;
618             mPhysicalAddress = hdmiDeviceInfo.mPhysicalAddress;
619             mPortId = hdmiDeviceInfo.mPortId;
620             mLogicalAddress = hdmiDeviceInfo.mLogicalAddress;
621             mDeviceType = hdmiDeviceInfo.mDeviceType;
622             mCecVersion = hdmiDeviceInfo.mCecVersion;
623             mVendorId = hdmiDeviceInfo.mVendorId;
624             mDisplayName = hdmiDeviceInfo.mDisplayName;
625             mDevicePowerStatus = hdmiDeviceInfo.mDevicePowerStatus;
626             mDeviceId = hdmiDeviceInfo.mDeviceId;
627             mAdopterId = hdmiDeviceInfo.mAdopterId;
628             mDeviceFeatures = hdmiDeviceInfo.mDeviceFeatures;
629         }
630 
631         /**
632          * Create a new {@link HdmiDeviceInfo} object.
633          */
634         @NonNull
build()635         public HdmiDeviceInfo build() {
636             return new HdmiDeviceInfo(this);
637         }
638 
639         /**
640          * Sets the value for {@link #getPhysicalAddress()}.
641          */
642         @NonNull
setPhysicalAddress(int physicalAddress)643         public Builder setPhysicalAddress(int physicalAddress) {
644             mPhysicalAddress = physicalAddress;
645             return this;
646         }
647 
648         /**
649          * Sets the value for {@link #getPortId()}.
650          */
651         @NonNull
setPortId(int portId)652         public Builder setPortId(int portId) {
653             mPortId = portId;
654             return this;
655         }
656 
657         /**
658          * Sets the value for {@link #getLogicalAddress()}.
659          */
660         @NonNull
setLogicalAddress(int logicalAddress)661         public Builder setLogicalAddress(int logicalAddress) {
662             mLogicalAddress = logicalAddress;
663             return this;
664         }
665 
666         /**
667          * Sets the value for {@link #getDeviceType()}.
668          */
669         @NonNull
setDeviceType(int deviceType)670         public Builder setDeviceType(int deviceType) {
671             mDeviceType = deviceType;
672             return this;
673         }
674 
675         /**
676          * Sets the value for {@link #getCecVersion()}.
677          */
678         @NonNull
setCecVersion(int hdmiCecVersion)679         public Builder setCecVersion(int hdmiCecVersion) {
680             mCecVersion = hdmiCecVersion;
681             return this;
682         }
683 
684         /**
685          * Sets the value for {@link #getVendorId()}.
686          */
687         @NonNull
setVendorId(int vendorId)688         public Builder setVendorId(int vendorId) {
689             mVendorId = vendorId;
690             return this;
691         }
692 
693         /**
694          * Sets the value for {@link #getDisplayName()}.
695          */
696         @NonNull
setDisplayName(@onNull String displayName)697         public Builder setDisplayName(@NonNull String displayName) {
698             mDisplayName = displayName;
699             return this;
700         }
701 
702         /**
703          * Sets the value for {@link #getDevicePowerStatus()}.
704          */
705         @NonNull
setDevicePowerStatus(int devicePowerStatus)706         public Builder setDevicePowerStatus(int devicePowerStatus) {
707             mDevicePowerStatus = devicePowerStatus;
708             return this;
709         }
710 
711         /**
712          * Sets the value for {@link #getDeviceFeatures()}.
713          */
714         @NonNull
setDeviceFeatures(DeviceFeatures deviceFeatures)715         public Builder setDeviceFeatures(DeviceFeatures deviceFeatures) {
716             this.mDeviceFeatures = deviceFeatures;
717             return this;
718         }
719 
720         /**
721          * Sets the value for {@link #getDeviceId()}.
722          */
723         @NonNull
setDeviceId(int deviceId)724         public Builder setDeviceId(int deviceId) {
725             mDeviceId = deviceId;
726             return this;
727         }
728 
729         /**
730          * Sets the value for {@link #getAdopterId()}.
731          */
732         @NonNull
setAdopterId(int adopterId)733         public Builder setAdopterId(int adopterId) {
734             mAdopterId = adopterId;
735             return this;
736         }
737 
738         /**
739          * Updates the value for {@link #getDeviceFeatures()} with a new set of device features.
740          * New information overrides the old, except when feature support was unknown.
741          */
742         @NonNull
updateDeviceFeatures(DeviceFeatures deviceFeatures)743         public Builder updateDeviceFeatures(DeviceFeatures deviceFeatures) {
744             mDeviceFeatures = mDeviceFeatures.toBuilder().update(deviceFeatures).build();
745             return this;
746         }
747     }
748 }
749