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