HdmiControlManager.java revision 2e8f1b6399089626b4f0249427626ba6e63a62ef
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 17package android.hardware.hdmi; 18 19import android.annotation.Nullable; 20import android.annotation.SdkConstant; 21import android.annotation.SdkConstant.SdkConstantType; 22import android.annotation.SystemApi; 23import android.os.RemoteException; 24 25/** 26 * The {@link HdmiControlManager} class is used to send HDMI control messages 27 * to attached CEC devices. 28 * 29 * <p>Provides various HDMI client instances that represent HDMI-CEC logical devices 30 * hosted in the system. {@link #getTvClient()}, for instance will return an 31 * {@link HdmiTvClient} object if the system is configured to host one. Android system 32 * can host more than one logical CEC devices. If multiple types are configured they 33 * all work as if they were independent logical devices running in the system. 34 * 35 * @hide 36 */ 37@SystemApi 38public final class HdmiControlManager { 39 @Nullable private final IHdmiControlService mService; 40 41 /** 42 * Broadcast Action: Display OSD message. 43 * <p>Send when the service has a message to display on screen for events 44 * that need user's attention such as ARC status change. 45 * <p>Always contains the extra fields {@link #EXTRA_MESSAGE_ID}. 46 * <p>Requires {@link android.Manifest.permission#HDMI_CEC} to receive. 47 */ 48 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 49 public static final String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE"; 50 51 // --- Messages for ACTION_OSD_MESSAGE --- 52 /** 53 * Message that ARC enabled device is connected to invalid port (non-ARC port). 54 */ 55 public static final int OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT = 1; 56 57 /** 58 * Message used by TV to receive volume status from Audio Receiver. It should check volume value 59 * that is retrieved from extra value with the key {@link #EXTRA_MESSAGE_EXTRAM_PARAM1}. If the 60 * value is in range of [0,100], it is current volume of Audio Receiver. And there is another 61 * value, {@link #AVR_VOLUME_MUTED}, which is used to inform volume mute. 62 */ 63 public static final int OSD_MESSAGE_AVR_VOLUME_CHANGED = 2; 64 65 /** 66 * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the ID of 67 * the message to display on screen. 68 */ 69 public static final String EXTRA_MESSAGE_ID = "android.hardware.hdmi.extra.MESSAGE_ID"; 70 /** 71 * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the extra value 72 * of the message. 73 */ 74 public static final String EXTRA_MESSAGE_EXTRAM_PARAM1 = 75 "android.hardware.hdmi.extra.MESSAGE_EXTRA_PARAM1"; 76 77 /** 78 * Volume value for mute state. 79 */ 80 public static final int AVR_VOLUME_MUTED = 101; 81 82 public static final int POWER_STATUS_UNKNOWN = -1; 83 public static final int POWER_STATUS_ON = 0; 84 public static final int POWER_STATUS_STANDBY = 1; 85 public static final int POWER_STATUS_TRANSIENT_TO_ON = 2; 86 public static final int POWER_STATUS_TRANSIENT_TO_STANDBY = 3; 87 88 public static final int RESULT_SUCCESS = 0; 89 public static final int RESULT_TIMEOUT = 1; 90 public static final int RESULT_SOURCE_NOT_AVAILABLE = 2; 91 public static final int RESULT_TARGET_NOT_AVAILABLE = 3; 92 public static final int RESULT_ALREADY_IN_PROGRESS = 4; 93 public static final int RESULT_EXCEPTION = 5; 94 public static final int RESULT_INCORRECT_MODE = 6; 95 public static final int RESULT_COMMUNICATION_FAILED = 7; 96 97 public static final int DEVICE_EVENT_ADD_DEVICE = 1; 98 public static final int DEVICE_EVENT_REMOVE_DEVICE = 2; 99 public static final int DEVICE_EVENT_UPDATE_DEVICE = 3; 100 101 // --- One Touch Recording success result 102 /** Recording currently selected source. Indicates the status of a recording. */ 103 public static final int ONE_TOUCH_RECORD_RECORDING_CURRENTLY_SELECTED_SOURCE = 0x01; 104 /** Recording Digital Service. Indicates the status of a recording. */ 105 public static final int ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE = 0x02; 106 /** Recording Analogue Service. Indicates the status of a recording. */ 107 public static final int ONE_TOUCH_RECORD_RECORDING_ANALOGUE_SERVICE = 0x03; 108 /** Recording External input. Indicates the status of a recording. */ 109 public static final int ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT = 0x04; 110 111 // --- One Touch Record failure result 112 /** No recording – unable to record Digital Service. No suitable tuner. */ 113 public static final int ONE_TOUCH_RECORD_UNABLE_DIGITAL_SERVICE = 0x05; 114 /** No recording – unable to record Analogue Service. No suitable tuner. */ 115 public static final int ONE_TOUCH_RECORD_UNABLE_ANALOGUE_SERVICE = 0x06; 116 /** 117 * No recording – unable to select required service. as suitable tuner, but the requested 118 * parameters are invalid or out of range for that tuner. 119 */ 120 public static final int ONE_TOUCH_RECORD_UNABLE_SELECTED_SERVICE = 0x07; 121 /** No recording – invalid External plug number */ 122 public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PLUG_NUMBER = 0x09; 123 /** No recording – invalid External Physical Address */ 124 public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 0x0A; 125 /** No recording – CA system not supported */ 126 public static final int ONE_TOUCH_RECORD_UNSUPPORTED_CA = 0x0B; 127 /** No Recording – No or Insufficient CA Entitlements” */ 128 public static final int ONE_TOUCH_RECORD_NO_OR_INSUFFICIENT_CA_ENTITLEMENTS = 0x0C; 129 /** No recording – Not allowed to copy source. Source is “copy never”. */ 130 public static final int ONE_TOUCH_RECORD_DISALLOW_TO_COPY = 0x0D; 131 /** No recording – No further copies allowed */ 132 public static final int ONE_TOUCH_RECORD_DISALLOW_TO_FUTHER_COPIES = 0x0E; 133 /** No recording – No media */ 134 public static final int ONE_TOUCH_RECORD_NO_MEDIA = 0x10; 135 /** No recording – playing */ 136 public static final int ONE_TOUCH_RECORD_PLAYING = 0x11; 137 /** No recording – already recording */ 138 public static final int ONE_TOUCH_RECORD_ALREADY_RECORDING = 0x12; 139 /** No recording – media protected */ 140 public static final int ONE_TOUCH_RECORD_MEDIA_PROTECTED = 0x13; 141 /** No recording – no source signal */ 142 public static final int ONE_TOUCH_RECORD_NO_SOURCE_SIGNAL = 0x14; 143 /** No recording – media problem */ 144 public static final int ONE_TOUCH_RECORD_MEDIA_PROBLEM = 0x15; 145 /** No recording – not enough space available */ 146 public static final int ONE_TOUCH_RECORD_NOT_ENOUGH_SPACE = 0x16; 147 /** No recording – Parental Lock On */ 148 public static final int ONE_TOUCH_RECORD_PARENT_LOCK_ON = 0x17; 149 /** Recording terminated normally */ 150 public static final int ONE_TOUCH_RECORD_RECORDING_TERMINATED_NORMALLY = 0x1A; 151 /** Recording has already terminated */ 152 public static final int ONE_TOUCH_RECORD_RECORDING_ALREADY_TERMINATED = 0x1B; 153 /** No recording – other reason */ 154 public static final int ONE_TOUCH_RECORD_OTHER_REASON = 0x1F; 155 // From here extra message for recording that is not mentioned in CEC spec 156 /** No recording. Previous recording request in progress. */ 157 public static final int ONE_TOUCH_RECORD_PREVIOUS_RECORDING_IN_PROGRESS = 0x30; 158 /** No recording. Please check recorder and connection. */ 159 public static final int ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION = 0x31; 160 /** Cannot record currently displayed source. */ 161 public static final int ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN = 0x32; 162 /** CEC is disabled. */ 163 public static final int ONE_TOUCH_RECORD_CEC_DISABLED = 0x33; 164 165 // --- Types for timer recording 166 /** Timer recording type for digital service source. */ 167 public static final int TIMER_RECORDING_TYPE_DIGITAL = 1; 168 /** Timer recording type for analogue service source. */ 169 public static final int TIMER_RECORDING_TYPE_ANALOGUE = 2; 170 /** Timer recording type for external source. */ 171 public static final int TIMER_RECORDING_TYPE_EXTERNAL = 3; 172 173 // --- Timer Status Data 174 /** [Timer Status Data/Media Info] - Media present and not protected. */ 175 public static final int TIMER_STATUS_MEDIA_INFO_PRESENT_NOT_PROTECTED = 0x0; 176 /** [Timer Status Data/Media Info] - Media present, but protected. */ 177 public static final int TIMER_STATUS_MEDIA_INFO_PRESENT_PROTECTED = 0x1; 178 /** [Timer Status Data/Media Info] - Media not present. */ 179 public static final int TIMER_STATUS_MEDIA_INFO_NOT_PRESENT = 0x2; 180 181 /** [Timer Status Data/Programmed Info] - Enough space available for recording. */ 182 public static final int TIMER_STATUS_PROGRAMMED_INFO_ENOUGH_SPACE = 0x8; 183 /** [Timer Status Data/Programmed Info] - Not enough space available for recording. */ 184 public static final int TIMER_STATUS_PROGRAMMED_INFO_NOT_ENOUGH_SPACE = 0x9; 185 /** [Timer Status Data/Programmed Info] - Might not enough space available for recording. */ 186 public static final int TIMER_STATUS_PROGRAMMED_INFO_MIGHT_NOT_ENOUGH_SPACE = 0xB; 187 /** [Timer Status Data/Programmed Info] - No media info available. */ 188 public static final int TIMER_STATUS_PROGRAMMED_INFO_NO_MEDIA_INFO = 0xA; 189 190 /** [Timer Status Data/Not Programmed Error Info] - No free timer available. */ 191 public static final int TIMER_STATUS_NOT_PROGRAMMED_NO_FREE_TIME = 0x1; 192 /** [Timer Status Data/Not Programmed Error Info] - Date out of range. */ 193 public static final int TIMER_STATUS_NOT_PROGRAMMED_DATE_OUT_OF_RANGE = 0x2; 194 /** [Timer Status Data/Not Programmed Error Info] - Recording Sequence error. */ 195 public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_SEQUENCE = 0x3; 196 /** [Timer Status Data/Not Programmed Error Info] - Invalid External Plug Number. */ 197 public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_EXTERNAL_PLUG_NUMBER = 0x4; 198 /** [Timer Status Data/Not Programmed Error Info] - Invalid External Physical Address. */ 199 public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_EXTERNAL_PHYSICAL_NUMBER = 0x5; 200 /** [Timer Status Data/Not Programmed Error Info] - CA system not supported. */ 201 public static final int TIMER_STATUS_NOT_PROGRAMMED_CA_NOT_SUPPORTED = 0x6; 202 /** [Timer Status Data/Not Programmed Error Info] - No or insufficient CA Entitlements. */ 203 public static final int TIMER_STATUS_NOT_PROGRAMMED_NO_CA_ENTITLEMENTS = 0x7; 204 /** [Timer Status Data/Not Programmed Error Info] - Does not support resolution. */ 205 public static final int TIMER_STATUS_NOT_PROGRAMMED_UNSUPPORTED_RESOLUTION = 0x8; 206 /** [Timer Status Data/Not Programmed Error Info] - Parental Lock On. */ 207 public static final int TIMER_STATUS_NOT_PROGRAMMED_PARENTAL_LOCK_ON= 0x9; 208 /** [Timer Status Data/Not Programmed Error Info] - Clock Failure. */ 209 public static final int TIMER_STATUS_NOT_PROGRAMMED_CLOCK_FAILURE = 0xA; 210 /** [Timer Status Data/Not Programmed Error Info] - Duplicate: already programmed. */ 211 public static final int TIMER_STATUS_NOT_PROGRAMMED_DUPLICATED = 0xE; 212 213 // --- Extra result value for timer recording. 214 /** No extra error. */ 215 public static final int TIMER_RECORDING_RESULT_EXTRA_NO_ERROR = 0x00; 216 /** No timer recording - check recorder and connection. */ 217 public static final int TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION = 0x01; 218 /** No timer recording - cannot record selected source. */ 219 public static final int TIMER_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE = 0x02; 220 /** CEC is disabled. */ 221 public static final int TIMER_RECORDING_RESULT_EXTRA_CEC_DISABLED = 0x03; 222 223 // -- Timer cleared status data code used for result of onClearTimerRecordingResult. 224 /** Timer not cleared – recording. */ 225 public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_RECORDING = 0x00; 226 /** Timer not cleared – no matching. */ 227 public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_NO_MATCHING = 0x01; 228 /** Timer not cleared – no info available. */ 229 public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_NO_INFO_AVAILABLE = 0x02; 230 /** Timer cleared. */ 231 public static final int CLEAR_TIMER_STATUS_TIMER_CLEARED = 0x80; 232 /** Clear timer error - check recorder and connection. */ 233 public static final int CLEAR_TIMER_STATUS_CHECK_RECORDER_CONNECTION = 0xA0; 234 /** Clear timer error - cannot clear timer for selected source. */ 235 public static final int CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE = 0xA1; 236 /** Clear timer error - CEC is disabled. */ 237 public static final int CLEAR_TIMER_STATUS_CEC_DISABLE = 0xA2; 238 239 // True if we have a logical device of type playback hosted in the system. 240 private final boolean mHasPlaybackDevice; 241 // True if we have a logical device of type TV hosted in the system. 242 private final boolean mHasTvDevice; 243 244 /** 245 * @hide - hide this constructor because it has a parameter of type 246 * IHdmiControlService, which is a system private class. The right way 247 * to create an instance of this class is using the factory 248 * Context.getSystemService. 249 */ 250 public HdmiControlManager(IHdmiControlService service) { 251 mService = service; 252 int[] types = null; 253 if (mService != null) { 254 try { 255 types = mService.getSupportedTypes(); 256 } catch (RemoteException e) { 257 // Do nothing. 258 } 259 } 260 mHasTvDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_TV); 261 mHasPlaybackDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_PLAYBACK); 262 } 263 264 private static boolean hasDeviceType(int[] types, int type) { 265 if (types == null) { 266 return false; 267 } 268 for (int t : types) { 269 if (t == type) { 270 return true; 271 } 272 } 273 return false; 274 } 275 276 /** 277 * Gets an object that represents an HDMI-CEC logical device of a specified type. 278 * 279 * @param type CEC device type 280 * @return {@link HdmiClient} instance. {@code null} on failure. 281 * See {@link HdmiDeviceInfo#DEVICE_PLAYBACK} 282 * See {@link HdmiDeviceInfo#DEVICE_TV} 283 */ 284 @Nullable 285 public HdmiClient getClient(int type) { 286 if (mService == null) { 287 return null; 288 } 289 switch (type) { 290 case HdmiDeviceInfo.DEVICE_TV: 291 return mHasTvDevice ? new HdmiTvClient(mService) : null; 292 case HdmiDeviceInfo.DEVICE_PLAYBACK: 293 return mHasPlaybackDevice ? new HdmiPlaybackClient(mService) : null; 294 default: 295 return null; 296 } 297 } 298 299 /** 300 * Gets an object that represents an HDMI-CEC logical device of type playback on the system. 301 * 302 * <p>Used to send HDMI control messages to other devices like TV or audio amplifier through 303 * HDMI bus. It is also possible to communicate with other logical devices hosted in the same 304 * system if the system is configured to host more than one type of HDMI-CEC logical devices. 305 * 306 * @return {@link HdmiPlaybackClient} instance. {@code null} on failure. 307 */ 308 @Nullable 309 public HdmiPlaybackClient getPlaybackClient() { 310 return (HdmiPlaybackClient) getClient(HdmiDeviceInfo.DEVICE_PLAYBACK); 311 } 312 313 /** 314 * Gets an object that represents an HDMI-CEC logical device of type TV on the system. 315 * 316 * <p>Used to send HDMI control messages to other devices and manage them through 317 * HDMI bus. It is also possible to communicate with other logical devices hosted in the same 318 * system if the system is configured to host more than one type of HDMI-CEC logical devices. 319 * 320 * @return {@link HdmiTvClient} instance. {@code null} on failure. 321 */ 322 @Nullable 323 public HdmiTvClient getTvClient() { 324 return (HdmiTvClient) getClient(HdmiDeviceInfo.DEVICE_TV); 325 } 326 327 /** 328 * Listener used to get hotplug event from HDMI port. 329 */ 330 public interface HotplugEventListener { 331 void onReceived(HdmiHotplugEvent event); 332 } 333 334 /** 335 * Listener used to get vendor-specific commands. 336 */ 337 public interface VendorCommandListener { 338 /** 339 * Called when a vendor command is received. 340 * 341 * @param srcAddress source logical address 342 * @param params vendor-specific parameters 343 * @param hasVendorId {@code true} if the command is <Vendor Command 344 * With ID>. The first 3 bytes of params is vendor id. 345 */ 346 void onReceived(int srcAddress, byte[] params, boolean hasVendorId); 347 } 348 349 /** 350 * Adds a listener to get informed of {@link HdmiHotplugEvent}. 351 * 352 * <p>To stop getting the notification, 353 * use {@link #removeHotplugEventListener(HotplugEventListener)}. 354 * 355 * @param listener {@link HotplugEventListener} instance 356 * @see HdmiControlManager#removeHotplugEventListener(HotplugEventListener) 357 */ 358 public void addHotplugEventListener(HotplugEventListener listener) { 359 if (mService == null) { 360 return; 361 } 362 try { 363 mService.addHotplugEventListener(getHotplugEventListenerWrapper(listener)); 364 } catch (RemoteException e) { 365 // Do nothing. 366 } 367 } 368 369 /** 370 * Removes a listener to stop getting informed of {@link HdmiHotplugEvent}. 371 * 372 * @param listener {@link HotplugEventListener} instance to be removed 373 */ 374 public void removeHotplugEventListener(HotplugEventListener listener) { 375 if (mService == null) { 376 return; 377 } 378 try { 379 mService.removeHotplugEventListener(getHotplugEventListenerWrapper(listener)); 380 } catch (RemoteException e) { 381 // Do nothing. 382 } 383 } 384 385 private IHdmiHotplugEventListener getHotplugEventListenerWrapper( 386 final HotplugEventListener listener) { 387 return new IHdmiHotplugEventListener.Stub() { 388 @Override 389 public void onReceived(HdmiHotplugEvent event) { 390 listener.onReceived(event);; 391 } 392 }; 393 } 394} 395