Home | History | Annotate | Download | only in tv
      1 <html devsite>
      2   <head>
      3     <title>HDMI-CEC Control Service</title>
      4     <meta name="project_path" value="/_project.yaml" />
      5     <meta name="book_path" value="/_book.yaml" />
      6   </head>
      7   <body>
      8   <!--
      9       Copyright 2017 The Android Open Source Project
     10 
     11       Licensed under the Apache License, Version 2.0 (the "License");
     12       you may not use this file except in compliance with the License.
     13       You may obtain a copy of the License at
     14 
     15           http://www.apache.org/licenses/LICENSE-2.0
     16 
     17       Unless required by applicable law or agreed to in writing, software
     18       distributed under the License is distributed on an "AS IS" BASIS,
     19       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     20       See the License for the specific language governing permissions and
     21       limitations under the License.
     22   -->
     23 
     24 
     25 
     26 <h2 id=intro>Introduction</h2>
     27 
     28 <p>The High-Definition Multimedia Interface Consumer Electronics Control (HDMI-CEC) standard allows mulitmedia consumer products to communicate and
     29 exchange information with each other. HDMI-CEC supports many features, like
     30 Remote Control Passthrough and System Audio Control, but one of the most
     31 popular is One Touch Play. One Touch Play lets a media source device turn on
     32 the TV and switch its input port automatically, so you dont have to search for
     33 the TV remote to switch from your Chromecast to Blu-ray player.</p>
     34 
     35 <p>Most manufacturers have adopted HDMI-CEC so their devices work with other
     36 companies devices. But because each manufacturer implements the HDMI-CEC
     37 standard in different ways, devices dont always understand each other and
     38 supported features vary between devices. Because of this variance, consumers
     39 cant safely assume that two products that claim CEC support are completely
     40 compatible.</p>
     41 
     42 <h2 id=solution>Solution</h2>
     43 
     44 
     45 <p>With the introduction of the Android TV Input Framework (TIF), HDMI-CEC brings
     46 together all connected devices and minimizes compatibility issues. Android has
     47 created a system service called <code>HdmiControlService</code> to alleviate these pain points.</p>
     48 
     49 <p>By offering <code>HdmiControlService</code> as a part of the Android ecosystem, Android hopes to provide:</p>
     50 
     51 <ul>
     52   <li>A standard implementation of HDMI-CEC for all manufacturers, which will reduce
     53 device incompatibility. Previously, manufacturers had to develop their own
     54 implementations of HDMI-CEC or use third-party solutions.</li>
     55   <li>A service that is well-tested against numerous HDMI-CEC devices already in the
     56 market. Android has been conducting rigorous research on compatibility issues
     57 found among the products and collecting useful advice from device implementers experienced
     58 in the technology. The CEC service is designed to keep a healthy balance
     59 between the standard and modifications to that standard so that it works with
     60 the products that people already use.</li>
     61 </ul>
     62 
     63 <h2 id=overall_design>Overall design</h2>
     64 
     65 
     66 <p><code>HdmiControlService</code> is connected with the rest of the system like TV Input Framework (TIF), Audio service, and Power service to implement the various features the standard
     67 specifies.</p>
     68 
     69 <p>See the following diagram for a depiction of the switch from a custom CEC
     70 controller to an implementation of the simpler HDMI-CEC hardware abstraction
     71 layer (HAL).</p>
     72 
     73 <img src="/devices/tv/images/HDMI_Control_Service.png" alt="Diagram that shows how HDMI-CEC was implemented before and after Android 5.0">
     74 
     75 <p class="img-caption"><strong>Figure 1.</strong> HDMI Control Service replacement</p>
     76 
     77 <h2 id=implementation>Implementation</h2>
     78 
     79 
     80 <p>See the following diagram for a detailed view of the HDMI control service.</p>
     81 
     82 <img src="/devices/tv/images/HDMI_Control_Service_Flow.png" alt="Image that shows how HDMI Control service details">
     83 
     84 <p class="img-caption"><strong>Figure 2.</strong> HDMI Control Service details</p>
     85 
     86 <p>Here are the key ingredients to a proper Android HDMI-CEC implementation:</p>
     87 
     88 <ul>
     89   <li> A manager class <code>HdmiControlManager</code> provides privileged apps with the API. System services like TV Input Manager service and Audio service can grab the service directly.</li>
     90   <li> The service is designed to allow hosting more than one type of logical device.</li>
     91   <li> HDMI-CEC is connected with the hardware via a hardware abstraction layer (HAL)
     92 to simplify handling differences of the protocol and signalling mechanisms
     93 between the devices. The HAL definition is available for device manufacturers
     94 to use to implement the HAL layer.</li>
     95 </ul>
     96 
     97 <p class="note"><strong>Note</strong>: Device manufacturers should add the following line into <code>PRODUCT_COPY_FILES</code> in <code>device.mk</code>.</p>
     98 
     99 <pre class="devsite-click-to-copy">
    100 PRODUCT_COPY_FILES += \
    101 frameworks/native/data/etc/android.hardware.hdmi.cec.xml:system/etc/permissions/android.hardware.hdmi.cec.xml
    102 </pre>
    103 
    104 
    105 <p>Depending on whether your device is a HDMI sink device or a HDMI source device,
    106 device manufacturers need to set <code>ro.hdmi.device_type</code> in <code>device.mk</code> for <code>HdmiControlService</code> to work correctly.</p>
    107 
    108 <p>For HDMI source devices, like Over the Top (OTT) boxes, set:</p>
    109 
    110 <pre class="devsite-click-to-copy">
    111 PRODUCT_PROPERTY_OVERRIDES += ro.hdmi.device_type=<strong>4</strong>
    112 </pre>
    113 
    114 <p>For HDMI sink devices, like panel TVs, set:</p>
    115 
    116 <pre class="devsite-click-to-copy">
    117 PRODUCT_PROPERTY_OVERRIDES += ro.hdmi.device_type=<strong>0</strong></pre>
    118 
    119 
    120 <ul>
    121   <li> A device manufacturer-provided proprietary CEC controller cannot coexist with <code>HdmiControlService</code>. It must be disabled or removed. Common requirements for this come from the need to handle manufacturer-specific commands. The manufacturer-specific
    122 command handler should be incorporated into the service by extending/modifying
    123 it. This work is left to the device manufacturer and not specified by Android.
    124 Note that any change made in the service for manufacturer-specific commands
    125 must not interfere with the way standard commands are handled or the device
    126 will not be Android compatible.</li>
    127   <li> Access to the HDMI-CEC service is guarded with the protection level <code>SignatureOrSystem</code>. Only system components or the apps placed in <code>/system/priv-app</code> can access the service. This is to protect the service from abuse by apps with malicious intent.</li>
    128 </ul>
    129 
    130 <p>Android supports type <code>TV/Display(0)</code> and <code>playback device(4)</code>, which can issue the One Touch Play command to display. The other types (tuner
    131 and recorder) are currently not supported.</p>
    132 
    133 <h2 id=hdmi-cec_hal_definition>HDMI-CEC HAL definition</h2>
    134 
    135 
    136 <p>In order to have the service in action, the HDMI-CEC HAL needs to be
    137 implemented to the definition provided by Android. It abstracts differences in
    138 the hardware level and exposes the primitive operations (allocate/read/write,
    139 etc.) to the upper layer through API.</p>
    140 
    141 <p>The API calls that device manufacturers must support are:</p>
    142 
    143 <h3 id=tx_rx_events>TX/RX/Events</h3>
    144 <ul>
    145   <li><code>send_message</code></li>
    146   <li><code>register_event_callback</code></li>
    147 </ul>
    148 
    149 <h3 id=info>Info</h3>
    150 <ul>
    151   <li><code>get_physical_address</code></li>
    152   <li><code>get_version</code></li>
    153   <li><code>get_vendor_id</code></li>
    154   <li><code>get_port_info</code></li>
    155 </ul>
    156 
    157 <h3 id=logical_address>Logical Address</h3>
    158 <ul>
    159   <li><code>add_logical_address</code></li>
    160   <li><code>clear_logical_address</code></li>
    161 </ul>
    162 
    163 <h3 id=status>Status</h3>
    164 <ul>
    165   <li><code>is_connected set_option</code></li>
    166   <li><code>set_audio_return_channel</code></li>
    167 </ul>
    168 
    169 <p>Here is an excerpt of the HDMI-CEC HAL definition regarding APIs:</p>
    170 
    171 <pre class="devsite-click-to-copy">
    172 #ifndef ANDROID_INCLUDE_HARDWARE_HDMI_CEC_H
    173 #define ANDROID_INCLUDE_HARDWARE_HDMI_CEC_H
    174 
    175 ...
    176 
    177 /*
    178  * HDMI-CEC HAL interface definition.
    179  */
    180 typedef struct hdmi_cec_device {
    181     /**
    182      * Common methods of the HDMI-CEC device.  This *must* be the first member of
    183      * hdmi_cec_device as users of this structure will cast a hw_device_t to hdmi_cec_device
    184      * pointer in contexts where it's known the hw_device_t references a hdmi_cec_device.
    185      */
    186     struct hw_device_t common;
    187 
    188     /*
    189      * (*add_logical_address)() passes the logical address that will be used
    190      * in this system.
    191      *
    192      * HAL may use it to configure the hardware so that the CEC commands addressed
    193      * the given logical address can be filtered in. This method can be called
    194      * as many times as necessary in order to support multiple logical devices.
    195      * addr should be in the range of valid logical addresses for the call
    196      * to succeed.
    197      *
    198      * Returns 0 on success or -errno on error.
    199      */
    200     int (*add_logical_address)(const struct hdmi_cec_device* dev, cec_logical_address_t addr);
    201 
    202     /*
    203      * (*clear_logical_address)() tells HAL to reset all the logical addresses.
    204      *
    205      * It is used when the system doesn't need to process CEC command any more,
    206      * hence to tell HAL to stop receiving commands from the CEC bus, and change
    207      * the state back to the beginning.
    208      */
    209     void (*clear_logical_address)(const struct hdmi_cec_device* dev);
    210 
    211     /*
    212      * (*get_physical_address)() returns the CEC physical address. The
    213      * address is written to addr.
    214      *
    215      * The physical address depends on the topology of the network formed
    216      * by connected HDMI devices. It is therefore likely to change if the cable
    217      * is plugged off and on again. It is advised to call get_physical_address
    218      * to get the updated address when hot plug event takes place.
    219      *
    220      * Returns 0 on success or -errno on error.
    221      */
    222     int (*get_physical_address)(const struct hdmi_cec_device* dev, uint16_t* addr);
    223 
    224     /*
    225      * (*send_message)() transmits HDMI-CEC message to other HDMI device.
    226      *
    227      * The method should be designed to return in a certain amount of time not
    228      * hanging forever, which can happen if CEC signal line is pulled low for
    229      * some reason. HAL implementation should take the situation into account
    230      * so as not to wait forever for the message to get sent out.
    231      *
    232      * It should try retransmission at least once as specified in the standard.
    233      *
    234      * Returns error code. See HDMI_RESULT_SUCCESS, HDMI_RESULT_NACK, and
    235      * HDMI_RESULT_BUSY.
    236      */
    237     int (*send_message)(const struct hdmi_cec_device* dev, const cec_message_t*);
    238 
    239     /*
    240      * (*register_event_callback)() registers a callback that HDMI-CEC HAL
    241      * can later use for incoming CEC messages or internal HDMI events.
    242      * When calling from C++, use the argument arg to pass the calling object.
    243      * It will be passed back when the callback is invoked so that the context
    244      * can be retrieved.
    245      */
    246     void (*register_event_callback)(const struct hdmi_cec_device* dev,
    247             event_callback_t callback, void* arg);
    248 
    249     /*
    250      * (*get_version)() returns the CEC version supported by underlying hardware.
    251      */
    252     void (*get_version)(const struct hdmi_cec_device* dev, int* version);
    253 
    254     /*
    255      * (*get_vendor_id)() returns the identifier of the vendor. It is
    256      * the 24-bit unique company ID obtained from the IEEE Registration
    257      * Authority Committee (RAC).
    258      */
    259     void (*get_vendor_id)(const struct hdmi_cec_device* dev, uint32_t* vendor_id);
    260 
    261     /*
    262      * (*get_port_info)() returns the hdmi port information of underlying hardware.
    263      * info is the list of HDMI port information, and 'total' is the number of
    264      * HDMI ports in the system.
    265      */
    266     void (*get_port_info)(const struct hdmi_cec_device* dev,
    267             struct hdmi_port_info* list[], int* total);
    268 
    269     /*
    270      * (*set_option)() passes flags controlling the way HDMI-CEC service works down
    271      * to HAL implementation. Those flags will be used in case the feature needs
    272      * update in HAL itself, firmware or microcontroller.
    273      */
    274     void (*set_option)(const struct hdmi_cec_device* dev, int flag, int value);
    275 
    276     /*
    277      * (*set_audio_return_channel)() configures ARC circuit in the hardware logic
    278      * to start or stop the feature. Flag can be either 1 to start the feature
    279      * or 0 to stop it.
    280      *
    281      * Returns 0 on success or -errno on error.
    282      */
    283     void (*set_audio_return_channel)(const struct hdmi_cec_device* dev, int flag);
    284 
    285     /*
    286      * (*is_connected)() returns the connection status of the specified port.
    287      * Returns HDMI_CONNECTED if a device is connected, otherwise HDMI_NOT_CONNECTED.
    288      * The HAL should watch for +5V power signal to determine the status.
    289      */
    290     int (*is_connected)(const struct hdmi_cec_device* dev, int port);
    291 
    292     /* Reserved for future use to maximum 16 functions. Must be NULL. */
    293     void* reserved[16 - 11];
    294 } hdmi_cec_device_t;
    295 
    296 #endif /* ANDROID_INCLUDE_HARDWARE_HDMI_CEC_H */
    297 </pre>
    298 
    299 
    300 <p>The API lets the service make use of the hardware resource to send/receive
    301 HDMI-CEC commands, configure necessary settings, and (optionally) communicate
    302 with the microprocessor in the underlying platform that will take over the CEC
    303 control while the Android system is in standby mode.</p>
    304 
    305 <h2 id=testing>Testing</h2>
    306 
    307 
    308 <p>Device manufacturers must test the APIs of the HDMI-CEC HAL with their own
    309 tools to make sure they provide expected functionality.</p>
    310 
    311   </body>
    312 </html>
    313