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.CallbackExecutor; 20 import android.annotation.IntDef; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.RequiresFeature; 24 import android.annotation.RequiresPermission; 25 import android.annotation.SdkConstant; 26 import android.annotation.SdkConstant.SdkConstantType; 27 import android.annotation.StringDef; 28 import android.annotation.SuppressLint; 29 import android.annotation.SystemApi; 30 import android.annotation.SystemService; 31 import android.content.Context; 32 import android.content.pm.PackageManager; 33 import android.os.Binder; 34 import android.os.RemoteException; 35 import android.sysprop.HdmiProperties; 36 import android.util.ArrayMap; 37 import android.util.Log; 38 39 import com.android.internal.annotations.GuardedBy; 40 import com.android.internal.util.ConcurrentUtils; 41 42 import java.lang.annotation.Retention; 43 import java.lang.annotation.RetentionPolicy; 44 import java.util.ArrayList; 45 import java.util.Arrays; 46 import java.util.List; 47 import java.util.Objects; 48 import java.util.concurrent.Executor; 49 import java.util.stream.Collectors; 50 51 /** 52 * The {@link HdmiControlManager} class is used to send HDMI control messages 53 * to attached CEC devices. It also allows to control the eARC feature. 54 * 55 * <p>Provides various HDMI client instances that represent HDMI-CEC logical devices 56 * hosted in the system. {@link #getTvClient()}, for instance will return an 57 * {@link HdmiTvClient} object if the system is configured to host one. Android system 58 * can host more than one logical CEC devices. If multiple types are configured they 59 * all work as if they were independent logical devices running in the system. 60 * 61 * @hide 62 */ 63 @SystemApi 64 @SystemService(Context.HDMI_CONTROL_SERVICE) 65 @RequiresFeature(PackageManager.FEATURE_HDMI_CEC) 66 public final class HdmiControlManager { 67 private static final String TAG = "HdmiControlManager"; 68 69 @Nullable private final IHdmiControlService mService; 70 71 private static final int INVALID_PHYSICAL_ADDRESS = 0xFFFF; 72 73 /** 74 * A cache of the current device's physical address. When device's HDMI out port 75 * is not connected to any device, it is set to {@link #INVALID_PHYSICAL_ADDRESS}. 76 * 77 * <p>Otherwise it is updated by the {@link ClientHotplugEventListener} registered 78 * with {@link com.android.server.hdmi.HdmiControlService} by the 79 * {@link #addHotplugEventListener(HotplugEventListener)} and the address is from 80 * {@link com.android.server.hdmi.HdmiControlService#getPortInfo()} 81 */ 82 @GuardedBy("mLock") 83 private int mLocalPhysicalAddress = INVALID_PHYSICAL_ADDRESS; 84 setLocalPhysicalAddress(int physicalAddress)85 private void setLocalPhysicalAddress(int physicalAddress) { 86 synchronized (mLock) { 87 mLocalPhysicalAddress = physicalAddress; 88 } 89 } 90 getLocalPhysicalAddress()91 private int getLocalPhysicalAddress() { 92 synchronized (mLock) { 93 return mLocalPhysicalAddress; 94 } 95 } 96 97 private final Object mLock = new Object(); 98 99 /** 100 * Broadcast Action: Display OSD message. 101 * <p>Send when the service has a message to display on screen for events 102 * that need user's attention such as ARC status change. 103 * <p>Always contains the extra fields {@link #EXTRA_MESSAGE_ID}. 104 * <p>Requires {@link android.Manifest.permission#HDMI_CEC} to receive. 105 */ 106 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 107 public static final String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE"; 108 109 // --- Messages for ACTION_OSD_MESSAGE --- 110 /** 111 * Message that ARC enabled device is connected to invalid port (non-ARC port). 112 */ 113 public static final int OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT = 1; 114 115 /** 116 * Message used by TV to receive volume status from Audio Receiver. It should check volume value 117 * that is retrieved from extra value with the key {@link #EXTRA_MESSAGE_EXTRA_PARAM1}. If the 118 * value is in range of [0,100], it is current volume of Audio Receiver. And there is another 119 * value, {@link #AVR_VOLUME_MUTED}, which is used to inform volume mute. 120 */ 121 public static final int OSD_MESSAGE_AVR_VOLUME_CHANGED = 2; 122 123 /** 124 * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the ID of 125 * the message to display on screen. 126 */ 127 public static final String EXTRA_MESSAGE_ID = "android.hardware.hdmi.extra.MESSAGE_ID"; 128 /** 129 * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the extra value 130 * of the message. 131 */ 132 public static final String EXTRA_MESSAGE_EXTRA_PARAM1 = 133 "android.hardware.hdmi.extra.MESSAGE_EXTRA_PARAM1"; 134 135 /** 136 * Used as an extra field in the Set Menu Language intent. Contains the requested locale. 137 * @hide 138 */ 139 public static final String EXTRA_LOCALE = "android.hardware.hdmi.extra.LOCALE"; 140 141 /** 142 * Volume value for mute state. 143 */ 144 public static final int AVR_VOLUME_MUTED = 101; 145 146 public static final int POWER_STATUS_UNKNOWN = -1; 147 public static final int POWER_STATUS_ON = 0; 148 public static final int POWER_STATUS_STANDBY = 1; 149 public static final int POWER_STATUS_TRANSIENT_TO_ON = 2; 150 public static final int POWER_STATUS_TRANSIENT_TO_STANDBY = 3; 151 152 @IntDef ({ 153 RESULT_SUCCESS, 154 RESULT_TIMEOUT, 155 RESULT_SOURCE_NOT_AVAILABLE, 156 RESULT_TARGET_NOT_AVAILABLE, 157 RESULT_ALREADY_IN_PROGRESS, 158 RESULT_EXCEPTION, 159 RESULT_INCORRECT_MODE, 160 RESULT_COMMUNICATION_FAILED, 161 }) 162 public @interface ControlCallbackResult {} 163 164 /** Control operation is successfully handled by the framework. */ 165 public static final int RESULT_SUCCESS = 0; 166 public static final int RESULT_TIMEOUT = 1; 167 /** Source device that the application is using is not available. */ 168 public static final int RESULT_SOURCE_NOT_AVAILABLE = 2; 169 /** Target device that the application is controlling is not available. */ 170 public static final int RESULT_TARGET_NOT_AVAILABLE = 3; 171 172 @Deprecated public static final int RESULT_ALREADY_IN_PROGRESS = 4; 173 public static final int RESULT_EXCEPTION = 5; 174 public static final int RESULT_INCORRECT_MODE = 6; 175 public static final int RESULT_COMMUNICATION_FAILED = 7; 176 177 public static final int DEVICE_EVENT_ADD_DEVICE = 1; 178 public static final int DEVICE_EVENT_REMOVE_DEVICE = 2; 179 public static final int DEVICE_EVENT_UPDATE_DEVICE = 3; 180 181 // --- One Touch Recording success result 182 /** Recording currently selected source. Indicates the status of a recording. */ 183 public static final int ONE_TOUCH_RECORD_RECORDING_CURRENTLY_SELECTED_SOURCE = 0x01; 184 /** Recording Digital Service. Indicates the status of a recording. */ 185 public static final int ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE = 0x02; 186 /** Recording Analogue Service. Indicates the status of a recording. */ 187 public static final int ONE_TOUCH_RECORD_RECORDING_ANALOGUE_SERVICE = 0x03; 188 /** Recording External input. Indicates the status of a recording. */ 189 public static final int ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT = 0x04; 190 191 // --- One Touch Record failure result 192 /** No recording – unable to record Digital Service. No suitable tuner. */ 193 public static final int ONE_TOUCH_RECORD_UNABLE_DIGITAL_SERVICE = 0x05; 194 /** No recording – unable to record Analogue Service. No suitable tuner. */ 195 public static final int ONE_TOUCH_RECORD_UNABLE_ANALOGUE_SERVICE = 0x06; 196 /** 197 * No recording – unable to select required service. as suitable tuner, but the requested 198 * parameters are invalid or out of range for that tuner. 199 */ 200 public static final int ONE_TOUCH_RECORD_UNABLE_SELECTED_SERVICE = 0x07; 201 /** No recording – invalid External plug number */ 202 public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PLUG_NUMBER = 0x09; 203 /** No recording – invalid External Physical Address */ 204 public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 0x0A; 205 /** No recording – CA system not supported */ 206 public static final int ONE_TOUCH_RECORD_UNSUPPORTED_CA = 0x0B; 207 /** No Recording – No or Insufficient CA Entitlements” */ 208 public static final int ONE_TOUCH_RECORD_NO_OR_INSUFFICIENT_CA_ENTITLEMENTS = 0x0C; 209 /** No recording – Not allowed to copy source. Source is “copy never”. */ 210 public static final int ONE_TOUCH_RECORD_DISALLOW_TO_COPY = 0x0D; 211 /** No recording – No further copies allowed */ 212 public static final int ONE_TOUCH_RECORD_DISALLOW_TO_FUTHER_COPIES = 0x0E; 213 /** No recording – No media */ 214 public static final int ONE_TOUCH_RECORD_NO_MEDIA = 0x10; 215 /** No recording – playing */ 216 public static final int ONE_TOUCH_RECORD_PLAYING = 0x11; 217 /** No recording – already recording */ 218 public static final int ONE_TOUCH_RECORD_ALREADY_RECORDING = 0x12; 219 /** No recording – media protected */ 220 public static final int ONE_TOUCH_RECORD_MEDIA_PROTECTED = 0x13; 221 /** No recording – no source signal */ 222 public static final int ONE_TOUCH_RECORD_NO_SOURCE_SIGNAL = 0x14; 223 /** No recording – media problem */ 224 public static final int ONE_TOUCH_RECORD_MEDIA_PROBLEM = 0x15; 225 /** No recording – not enough space available */ 226 public static final int ONE_TOUCH_RECORD_NOT_ENOUGH_SPACE = 0x16; 227 /** No recording – Parental Lock On */ 228 public static final int ONE_TOUCH_RECORD_PARENT_LOCK_ON = 0x17; 229 /** Recording terminated normally */ 230 public static final int ONE_TOUCH_RECORD_RECORDING_TERMINATED_NORMALLY = 0x1A; 231 /** Recording has already terminated */ 232 public static final int ONE_TOUCH_RECORD_RECORDING_ALREADY_TERMINATED = 0x1B; 233 /** No recording – other reason */ 234 public static final int ONE_TOUCH_RECORD_OTHER_REASON = 0x1F; 235 // From here extra message for recording that is not mentioned in CEC spec 236 /** No recording. Previous recording request in progress. */ 237 public static final int ONE_TOUCH_RECORD_PREVIOUS_RECORDING_IN_PROGRESS = 0x30; 238 /** No recording. Please check recorder and connection. */ 239 public static final int ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION = 0x31; 240 /** Cannot record currently displayed source. */ 241 public static final int ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN = 0x32; 242 /** CEC is disabled. */ 243 public static final int ONE_TOUCH_RECORD_CEC_DISABLED = 0x33; 244 245 // --- Types for timer recording 246 /** Timer recording type for digital service source. */ 247 public static final int TIMER_RECORDING_TYPE_DIGITAL = 1; 248 /** Timer recording type for analogue service source. */ 249 public static final int TIMER_RECORDING_TYPE_ANALOGUE = 2; 250 /** Timer recording type for external source. */ 251 public static final int TIMER_RECORDING_TYPE_EXTERNAL = 3; 252 253 // --- Timer Status Data 254 /** [Timer Status Data/Media Info] - Media present and not protected. */ 255 public static final int TIMER_STATUS_MEDIA_INFO_PRESENT_NOT_PROTECTED = 0x0; 256 /** [Timer Status Data/Media Info] - Media present, but protected. */ 257 public static final int TIMER_STATUS_MEDIA_INFO_PRESENT_PROTECTED = 0x1; 258 /** [Timer Status Data/Media Info] - Media not present. */ 259 public static final int TIMER_STATUS_MEDIA_INFO_NOT_PRESENT = 0x2; 260 261 /** [Timer Status Data/Programmed Info] - Enough space available for recording. */ 262 public static final int TIMER_STATUS_PROGRAMMED_INFO_ENOUGH_SPACE = 0x8; 263 /** [Timer Status Data/Programmed Info] - Not enough space available for recording. */ 264 public static final int TIMER_STATUS_PROGRAMMED_INFO_NOT_ENOUGH_SPACE = 0x9; 265 /** [Timer Status Data/Programmed Info] - Might not enough space available for recording. */ 266 public static final int TIMER_STATUS_PROGRAMMED_INFO_MIGHT_NOT_ENOUGH_SPACE = 0xB; 267 /** [Timer Status Data/Programmed Info] - No media info available. */ 268 public static final int TIMER_STATUS_PROGRAMMED_INFO_NO_MEDIA_INFO = 0xA; 269 270 /** [Timer Status Data/Not Programmed Error Info] - No free timer available. */ 271 public static final int TIMER_STATUS_NOT_PROGRAMMED_NO_FREE_TIME = 0x1; 272 /** [Timer Status Data/Not Programmed Error Info] - Date out of range. */ 273 public static final int TIMER_STATUS_NOT_PROGRAMMED_DATE_OUT_OF_RANGE = 0x2; 274 /** [Timer Status Data/Not Programmed Error Info] - Recording Sequence error. */ 275 public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_SEQUENCE = 0x3; 276 /** [Timer Status Data/Not Programmed Error Info] - Invalid External Plug Number. */ 277 public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_EXTERNAL_PLUG_NUMBER = 0x4; 278 /** [Timer Status Data/Not Programmed Error Info] - Invalid External Physical Address. */ 279 public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_EXTERNAL_PHYSICAL_NUMBER = 0x5; 280 /** [Timer Status Data/Not Programmed Error Info] - CA system not supported. */ 281 public static final int TIMER_STATUS_NOT_PROGRAMMED_CA_NOT_SUPPORTED = 0x6; 282 /** [Timer Status Data/Not Programmed Error Info] - No or insufficient CA Entitlements. */ 283 public static final int TIMER_STATUS_NOT_PROGRAMMED_NO_CA_ENTITLEMENTS = 0x7; 284 /** [Timer Status Data/Not Programmed Error Info] - Does not support resolution. */ 285 public static final int TIMER_STATUS_NOT_PROGRAMMED_UNSUPPORTED_RESOLUTION = 0x8; 286 /** [Timer Status Data/Not Programmed Error Info] - Parental Lock On. */ 287 public static final int TIMER_STATUS_NOT_PROGRAMMED_PARENTAL_LOCK_ON= 0x9; 288 /** [Timer Status Data/Not Programmed Error Info] - Clock Failure. */ 289 public static final int TIMER_STATUS_NOT_PROGRAMMED_CLOCK_FAILURE = 0xA; 290 /** [Timer Status Data/Not Programmed Error Info] - Duplicate: already programmed. */ 291 public static final int TIMER_STATUS_NOT_PROGRAMMED_DUPLICATED = 0xE; 292 293 // --- Extra result value for timer recording. 294 /** No extra error. */ 295 public static final int TIMER_RECORDING_RESULT_EXTRA_NO_ERROR = 0x00; 296 /** No timer recording - check recorder and connection. */ 297 public static final int TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION = 0x01; 298 /** No timer recording - cannot record selected source. */ 299 public static final int TIMER_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE = 0x02; 300 /** CEC is disabled. */ 301 public static final int TIMER_RECORDING_RESULT_EXTRA_CEC_DISABLED = 0x03; 302 303 // -- Timer cleared status data code used for result of onClearTimerRecordingResult. 304 /** Timer not cleared – recording. */ 305 public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_RECORDING = 0x00; 306 /** Timer not cleared – no matching. */ 307 public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_NO_MATCHING = 0x01; 308 /** Timer not cleared – no info available. */ 309 public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_NO_INFO_AVAILABLE = 0x02; 310 /** Timer cleared. */ 311 public static final int CLEAR_TIMER_STATUS_TIMER_CLEARED = 0x80; 312 /** Clear timer error - check recorder and connection. */ 313 public static final int CLEAR_TIMER_STATUS_CHECK_RECORDER_CONNECTION = 0xA0; 314 /** Clear timer error - cannot clear timer for selected source. */ 315 public static final int CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE = 0xA1; 316 /** Clear timer error - CEC is disabled. */ 317 public static final int CLEAR_TIMER_STATUS_CEC_DISABLE = 0xA2; 318 319 /** The HdmiControlService is started. */ 320 public static final int CONTROL_STATE_CHANGED_REASON_START = 0; 321 /** The state of HdmiControlService is changed by changing of settings. */ 322 public static final int CONTROL_STATE_CHANGED_REASON_SETTING = 1; 323 /** The HdmiControlService is enabled to wake up. */ 324 public static final int CONTROL_STATE_CHANGED_REASON_WAKEUP = 2; 325 /** The HdmiControlService will be disabled to standby. */ 326 public static final int CONTROL_STATE_CHANGED_REASON_STANDBY = 3; 327 328 // -- Whether the HDMI CEC is enabled or disabled. 329 /** 330 * HDMI CEC enabled. 331 * 332 * @see HdmiControlManager#CEC_SETTING_NAME_HDMI_CEC_ENABLED 333 */ 334 public static final int HDMI_CEC_CONTROL_ENABLED = 1; 335 /** 336 * HDMI CEC disabled. 337 * 338 * @see HdmiControlManager#CEC_SETTING_NAME_HDMI_CEC_ENABLED 339 */ 340 public static final int HDMI_CEC_CONTROL_DISABLED = 0; 341 /** 342 * @hide 343 * 344 * @see HdmiControlManager#CEC_SETTING_NAME_HDMI_CEC_ENABLED 345 */ 346 @IntDef(prefix = { "HDMI_CEC_CONTROL_" }, value = { 347 HDMI_CEC_CONTROL_ENABLED, 348 HDMI_CEC_CONTROL_DISABLED 349 }) 350 @Retention(RetentionPolicy.SOURCE) 351 public @interface HdmiCecControl {} 352 353 // -- Supported HDMI-CEC versions. 354 /** 355 * Version constant for HDMI-CEC v1.4b. 356 * 357 * @see HdmiControlManager#CEC_SETTING_NAME_HDMI_CEC_VERSION 358 */ 359 public static final int HDMI_CEC_VERSION_1_4_B = 0x05; 360 /** 361 * Version constant for HDMI-CEC v2.0. 362 * 363 * @see HdmiControlManager#CEC_SETTING_NAME_HDMI_CEC_VERSION 364 */ 365 public static final int HDMI_CEC_VERSION_2_0 = 0x06; 366 /** 367 * @see HdmiControlManager#CEC_SETTING_NAME_HDMI_CEC_VERSION 368 * @hide 369 */ 370 @IntDef(prefix = { "HDMI_CEC_VERSION_" }, value = { 371 HDMI_CEC_VERSION_1_4_B, 372 HDMI_CEC_VERSION_2_0 373 }) 374 @Retention(RetentionPolicy.SOURCE) 375 public @interface HdmiCecVersion {} 376 377 // -- Whether the Routing Control feature is enabled or disabled. 378 /** 379 * Routing Control feature enabled. 380 * 381 * @see HdmiControlManager#CEC_SETTING_NAME_ROUTING_CONTROL 382 */ 383 public static final int ROUTING_CONTROL_ENABLED = 1; 384 /** 385 * Routing Control feature disabled. 386 * 387 * @see HdmiControlManager#CEC_SETTING_NAME_ROUTING_CONTROL 388 */ 389 public static final int ROUTING_CONTROL_DISABLED = 0; 390 /** 391 * @see HdmiControlManager#CEC_SETTING_NAME_ROUTING_CONTROL 392 * @hide 393 */ 394 @IntDef(prefix = { "ROUTING_CONTROL_" }, value = { 395 ROUTING_CONTROL_ENABLED, 396 ROUTING_CONTROL_DISABLED 397 }) 398 @Retention(RetentionPolicy.SOURCE) 399 public @interface RoutingControl {} 400 401 // -- Whether the Soundbar mode feature is enabled or disabled. 402 /** 403 * Soundbar mode feature enabled. 404 * 405 * @see HdmiControlManager#CEC_SETTING_NAME_SOUNDBAR_MODE 406 */ 407 public static final int SOUNDBAR_MODE_ENABLED = 1; 408 /** 409 * Soundbar mode feature disabled. 410 * 411 * @see HdmiControlManager#CEC_SETTING_NAME_SOUNDBAR_MODE 412 */ 413 public static final int SOUNDBAR_MODE_DISABLED = 0; 414 /** 415 * @see HdmiControlManager#CEC_SETTING_NAME_SOUNDBAR_MODE 416 * @hide 417 */ 418 @IntDef(prefix = { "SOUNDBAR_MODE" }, value = { 419 SOUNDBAR_MODE_ENABLED, 420 SOUNDBAR_MODE_DISABLED 421 }) 422 @Retention(RetentionPolicy.SOURCE) 423 public @interface SoundbarMode {} 424 425 // -- Scope of CEC power control messages sent by a playback device. 426 /** 427 * Send CEC power control messages to TV only: 428 * Upon going to sleep, send {@code <Standby>} to TV only. 429 * Upon waking up, attempt to turn on the TV via {@code <One Touch Play>} but do not turn on the 430 * Audio system via {@code <System Audio Mode Request>}. 431 * 432 * @see HdmiControlManager#CEC_SETTING_NAME_POWER_CONTROL_MODE 433 */ 434 public static final String POWER_CONTROL_MODE_TV = "to_tv"; 435 /** 436 * Send CEC power control messages to TV and Audio System: 437 * Upon going to sleep, send {@code <Standby>} to TV and Audio system. 438 * Upon waking up, attempt to turn on the TV via {@code <One Touch Play>} and attempt to turn on 439 * the Audio system via {@code <System Audio Mode Request>}. 440 * 441 * @see HdmiControlManager#CEC_SETTING_NAME_POWER_CONTROL_MODE 442 */ 443 public static final String POWER_CONTROL_MODE_TV_AND_AUDIO_SYSTEM = "to_tv_and_audio_system"; 444 /** 445 * Broadcast CEC power control messages to all devices in the network: 446 * Upon going to sleep, send {@code <Standby>} to all devices in the network. 447 * Upon waking up, attempt to turn on the TV via {@code <One Touch Play>} and attempt to turn on 448 * the Audio system via {@code <System Audio Mode Request>}. 449 * 450 * @see HdmiControlManager#CEC_SETTING_NAME_POWER_CONTROL_MODE 451 */ 452 public static final String POWER_CONTROL_MODE_BROADCAST = "broadcast"; 453 /** 454 * Don't send any CEC power control messages: 455 * Upon going to sleep, do not send any {@code <Standby>} message. 456 * Upon waking up, do not turn on the TV via {@code <One Touch Play>} and do not turn on the 457 * Audio system via {@code <System Audio Mode Request>}. 458 * 459 * @see HdmiControlManager#CEC_SETTING_NAME_POWER_CONTROL_MODE 460 */ 461 public static final String POWER_CONTROL_MODE_NONE = "none"; 462 /** 463 * @see HdmiControlManager#CEC_SETTING_NAME_POWER_CONTROL_MODE 464 * @hide 465 */ 466 @StringDef(prefix = { "POWER_CONTROL_MODE_" }, value = { 467 POWER_CONTROL_MODE_TV, 468 POWER_CONTROL_MODE_TV_AND_AUDIO_SYSTEM, 469 POWER_CONTROL_MODE_BROADCAST, 470 POWER_CONTROL_MODE_NONE 471 }) 472 @Retention(RetentionPolicy.SOURCE) 473 public @interface PowerControlMode {} 474 475 // -- Which power state action should be taken when Active Source is lost. 476 /** 477 * No action to be taken. 478 * 479 * @see HdmiControlManager#CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST 480 */ 481 public static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE = "none"; 482 /** 483 * Go to standby immediately. 484 * 485 * @see HdmiControlManager#CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST 486 */ 487 public static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW = "standby_now"; 488 /** 489 * @see HdmiControlManager#CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST 490 * @hide 491 */ 492 @StringDef(prefix = { "POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_" }, value = { 493 POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE, 494 POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW 495 }) 496 @Retention(RetentionPolicy.SOURCE) 497 public @interface ActiveSourceLostBehavior {} 498 499 // -- Whether System Audio Control is enabled or disabled. 500 /** 501 * System Audio Control enabled. 502 * 503 * @see HdmiControlManager#CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL 504 */ 505 public static final int SYSTEM_AUDIO_CONTROL_ENABLED = 1; 506 /** 507 * System Audio Control disabled. 508 * 509 * @see HdmiControlManager#CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL 510 */ 511 public static final int SYSTEM_AUDIO_CONTROL_DISABLED = 0; 512 /** 513 * @see HdmiControlManager#CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL 514 * @hide 515 */ 516 @IntDef(prefix = { "SYSTEM_AUDIO_CONTROL_" }, value = { 517 SYSTEM_AUDIO_CONTROL_ENABLED, 518 SYSTEM_AUDIO_CONTROL_DISABLED 519 }) 520 @Retention(RetentionPolicy.SOURCE) 521 public @interface SystemAudioControl {} 522 523 // -- Whether System Audio Mode muting is enabled or disabled. 524 /** 525 * System Audio Mode muting enabled. 526 * 527 * @see HdmiControlManager#CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING 528 */ 529 public static final int SYSTEM_AUDIO_MODE_MUTING_ENABLED = 1; 530 /** 531 * System Audio Mode muting disabled. 532 * 533 * @see HdmiControlManager#CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING 534 */ 535 public static final int SYSTEM_AUDIO_MODE_MUTING_DISABLED = 0; 536 /** 537 * @see HdmiControlManager#CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING 538 * @hide 539 */ 540 @IntDef(prefix = { "SYSTEM_AUDIO_MODE_MUTING_" }, value = { 541 SYSTEM_AUDIO_MODE_MUTING_ENABLED, 542 SYSTEM_AUDIO_MODE_MUTING_DISABLED 543 }) 544 @Retention(RetentionPolicy.SOURCE) 545 public @interface SystemAudioModeMuting {} 546 547 // -- Whether the HDMI CEC volume control is enabled or disabled. 548 /** 549 * HDMI CEC enabled. 550 * 551 * @see HdmiControlManager#CEC_SETTING_NAME_VOLUME_CONTROL_MODE 552 */ 553 public static final int VOLUME_CONTROL_ENABLED = 1; 554 /** 555 * HDMI CEC disabled. 556 * 557 * @see HdmiControlManager#CEC_SETTING_NAME_VOLUME_CONTROL_MODE 558 */ 559 public static final int VOLUME_CONTROL_DISABLED = 0; 560 /** 561 * @see HdmiControlManager#CEC_SETTING_NAME_VOLUME_CONTROL_MODE 562 * @hide 563 */ 564 @IntDef(prefix = { "VOLUME_CONTROL_" }, value = { 565 VOLUME_CONTROL_ENABLED, 566 VOLUME_CONTROL_DISABLED 567 }) 568 @Retention(RetentionPolicy.SOURCE) 569 public @interface VolumeControl {} 570 571 // -- Whether TV Wake on One Touch Play is enabled or disabled. 572 /** 573 * TV Wake on One Touch Play enabled. 574 * 575 * @see HdmiControlManager#CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY 576 */ 577 public static final int TV_WAKE_ON_ONE_TOUCH_PLAY_ENABLED = 1; 578 /** 579 * TV Wake on One Touch Play disabled. 580 * 581 * @see HdmiControlManager#CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY 582 */ 583 public static final int TV_WAKE_ON_ONE_TOUCH_PLAY_DISABLED = 0; 584 /** 585 * @see HdmiControlManager#CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY 586 * @hide 587 */ 588 @IntDef(prefix = { "TV_WAKE_ON_ONE_TOUCH_PLAY_" }, value = { 589 TV_WAKE_ON_ONE_TOUCH_PLAY_ENABLED, 590 TV_WAKE_ON_ONE_TOUCH_PLAY_DISABLED 591 }) 592 @Retention(RetentionPolicy.SOURCE) 593 public @interface TvWakeOnOneTouchPlay {} 594 595 // -- Whether TV should send <Standby> on sleep. 596 /** 597 * Sending <Standby> on sleep. 598 * 599 * @see HdmiControlManager#CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP 600 */ 601 public static final int TV_SEND_STANDBY_ON_SLEEP_ENABLED = 1; 602 /** 603 * Not sending <Standby> on sleep. 604 * 605 * @see HdmiControlManager#CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP 606 */ 607 public static final int TV_SEND_STANDBY_ON_SLEEP_DISABLED = 0; 608 /** 609 * @see HdmiControlManager#CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP 610 * @hide 611 */ 612 @IntDef(prefix = { "TV_SEND_STANDBY_ON_SLEEP_" }, value = { 613 TV_SEND_STANDBY_ON_SLEEP_ENABLED, 614 TV_SEND_STANDBY_ON_SLEEP_DISABLED 615 }) 616 @Retention(RetentionPolicy.SOURCE) 617 public @interface TvSendStandbyOnSleep {} 618 619 // -- Whether a playback device should act on an incoming {@code <Set Menu Language>} message. 620 /** 621 * Confirmation dialog should be shown upon receiving the CEC message. 622 * 623 * @see HdmiControlManager#CEC_SETTING_NAME_SET_MENU_LANGUAGE 624 * @hide 625 */ 626 public static final int SET_MENU_LANGUAGE_ENABLED = 1; 627 /** 628 * The message should be ignored. 629 * 630 * @see HdmiControlManager#CEC_SETTING_NAME_SET_MENU_LANGUAGE 631 * @hide 632 */ 633 public static final int SET_MENU_LANGUAGE_DISABLED = 0; 634 /** 635 * @see HdmiControlManager#CEC_SETTING_NAME_SET_MENU_LANGUAGE 636 * @hide 637 */ 638 @IntDef(prefix = { "SET_MENU_LANGUAGE_" }, value = { 639 SET_MENU_LANGUAGE_ENABLED, 640 SET_MENU_LANGUAGE_DISABLED 641 }) 642 @Retention(RetentionPolicy.SOURCE) 643 public @interface SetMenuLanguage {} 644 645 // -- The RC profile of a TV panel. 646 /** 647 * RC profile none. 648 * 649 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_TV 650 * @hide 651 */ 652 public static final int RC_PROFILE_TV_NONE = 0x0; 653 /** 654 * RC profile 1. 655 * 656 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_TV 657 * @hide 658 */ 659 public static final int RC_PROFILE_TV_ONE = 0x2; 660 /** 661 * RC profile 2. 662 * 663 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_TV 664 * @hide 665 */ 666 public static final int RC_PROFILE_TV_TWO = 0x6; 667 /** 668 * RC profile 3. 669 * 670 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_TV 671 * @hide 672 */ 673 public static final int RC_PROFILE_TV_THREE = 0xA; 674 /** 675 * RC profile 4. 676 * 677 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_TV 678 * @hide 679 */ 680 public static final int RC_PROFILE_TV_FOUR = 0xE; 681 /** 682 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_TV 683 * @hide 684 */ 685 @IntDef(prefix = { "RC_PROFILE_TV_" }, value = { 686 RC_PROFILE_TV_NONE, 687 RC_PROFILE_TV_ONE, 688 RC_PROFILE_TV_TWO, 689 RC_PROFILE_TV_THREE, 690 RC_PROFILE_TV_FOUR 691 }) 692 @Retention(RetentionPolicy.SOURCE) 693 public @interface RcProfileTv {} 694 695 // -- RC profile parameter defining if a source handles a specific menu. 696 /** 697 * Handles the menu. 698 * 699 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_ROOT_MENU 700 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_SETUP_MENU 701 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU 702 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_TOP_MENU 703 * @see HdmiControlManager# 704 * CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU 705 * @hide 706 */ 707 public static final int RC_PROFILE_SOURCE_MENU_HANDLED = 1; 708 /** 709 * Doesn't handle the menu. 710 * 711 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_ROOT_MENU 712 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_SETUP_MENU 713 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU 714 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_TOP_MENU 715 * @see HdmiControlManager# 716 * CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU 717 * @hide 718 */ 719 public static final int RC_PROFILE_SOURCE_MENU_NOT_HANDLED = 0; 720 /** 721 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_ROOT_MENU 722 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_SETUP_MENU 723 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU 724 * @see HdmiControlManager#CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_TOP_MENU 725 * @see HdmiControlManager# 726 * CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU 727 * @hide 728 */ 729 @IntDef(prefix = { "RC_PROFILE_SOURCE_MENU_" }, value = { 730 RC_PROFILE_SOURCE_MENU_HANDLED, 731 RC_PROFILE_SOURCE_MENU_NOT_HANDLED 732 }) 733 @Retention(RetentionPolicy.SOURCE) 734 public @interface RcProfileSourceHandlesMenu {} 735 736 // -- Whether the Short Audio Descriptor (SAD) for a specific codec should be queried or not. 737 /** 738 * Query the SAD. 739 * 740 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_LPCM 741 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DD 742 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_MPEG1 743 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_MP3 744 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_MPEG2 745 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_AAC 746 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DTS 747 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_ATRAC 748 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_ONEBITAUDIO 749 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DDP 750 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DTSHD 751 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_TRUEHD 752 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DST 753 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_WMAPRO 754 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_MAX 755 */ 756 public static final int QUERY_SAD_ENABLED = 1; 757 /** 758 * Don't query the SAD. 759 * 760 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_LPCM 761 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DD 762 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_MPEG1 763 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_MP3 764 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_MPEG2 765 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_AAC 766 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DTS 767 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_ATRAC 768 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_ONEBITAUDIO 769 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DDP 770 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DTSHD 771 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_TRUEHD 772 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DST 773 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_WMAPRO 774 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_MAX 775 */ 776 public static final int QUERY_SAD_DISABLED = 0; 777 /** 778 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_LPCM 779 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DD 780 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_MPEG1 781 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_MP3 782 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_MPEG2 783 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_AAC 784 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DTS 785 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_ATRAC 786 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_ONEBITAUDIO 787 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DDP 788 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DTSHD 789 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_TRUEHD 790 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_DST 791 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_WMAPRO 792 * @see HdmiControlManager#CEC_SETTING_NAME_QUERY_SAD_MAX 793 * @hide 794 */ 795 @IntDef(prefix = { "QUERY_SAD_" }, value = { 796 QUERY_SAD_ENABLED, 797 QUERY_SAD_DISABLED 798 }) 799 @Retention(RetentionPolicy.SOURCE) 800 public @interface SadPresenceInQuery {} 801 802 // -- Whether eARC is enabled or disabled. 803 /** 804 * eARC enabled. 805 * 806 * @see HdmiControlManager#SETTING_NAME_EARC_ENABLED 807 */ 808 public static final int EARC_FEATURE_ENABLED = 1; 809 /** 810 * eARC disabled. 811 * 812 * @see HdmiControlManager#SETTING_NAME_EARC_ENABLED 813 */ 814 public static final int EARC_FEATURE_DISABLED = 0; 815 /** 816 * @hide 817 * 818 * @see HdmiControlManager#SETTING_NAME_EARC_ENABLED 819 */ 820 @IntDef(prefix = { "EARC_FEATURE" }, value = { 821 EARC_FEATURE_ENABLED, 822 EARC_FEATURE_DISABLED 823 }) 824 @Retention(RetentionPolicy.SOURCE) 825 public @interface EarcFeature {} 826 827 // -- Settings available in the CEC Configuration. 828 /** 829 * Name of a setting deciding whether the CEC is enabled. 830 * 831 * @see HdmiControlManager#setHdmiCecEnabled(int) 832 */ 833 public static final String CEC_SETTING_NAME_HDMI_CEC_ENABLED = "hdmi_cec_enabled"; 834 /** 835 * Name of a setting controlling the version of HDMI-CEC used. 836 * 837 * @see HdmiControlManager#setHdmiCecVersion(int) 838 */ 839 public static final String CEC_SETTING_NAME_HDMI_CEC_VERSION = "hdmi_cec_version"; 840 /** 841 * Name of a setting deciding whether the Routing Control feature is enabled. 842 * 843 * @see HdmiControlManager#setRoutingControl(int) 844 */ 845 public static final String CEC_SETTING_NAME_ROUTING_CONTROL = "routing_control"; 846 /** 847 * Name of a setting deciding whether the Soundbar mode feature is enabled. 848 * Before exposing this setting make sure the hardware supports it, otherwise, you may 849 * experience multiple issues. 850 * 851 * @see HdmiControlManager#setSoundbarMode(int) 852 */ 853 public static final String CEC_SETTING_NAME_SOUNDBAR_MODE = "soundbar_mode"; 854 /** 855 * Name of a setting deciding on the power control mode. 856 * 857 * @see HdmiControlManager#setPowerControlMode(String) 858 */ 859 public static final String CEC_SETTING_NAME_POWER_CONTROL_MODE = "power_control_mode"; 860 /** 861 * Name of a setting deciding on power state action when losing Active Source. 862 * 863 * @see HdmiControlManager#setPowerStateChangeOnActiveSourceLost(String) 864 */ 865 public static final String CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST = 866 "power_state_change_on_active_source_lost"; 867 /** 868 * Name of a setting deciding whether System Audio Control is enabled. 869 * 870 * @see HdmiControlManager#setSystemAudioControl(int) 871 */ 872 public static final String CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL = 873 "system_audio_control"; 874 /** 875 * Name of a setting deciding whether System Audio Muting is allowed. 876 * 877 * @see HdmiControlManager#setSystemAudioModeMuting(int) 878 */ 879 public static final String CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING = 880 "system_audio_mode_muting"; 881 /** 882 * Controls whether volume control commands via HDMI CEC are enabled. 883 * 884 * <p>Effects on different device types: 885 * <table> 886 * <tr><th>HDMI CEC device type</th><th>0: disabled</th><th>1: enabled</th></tr> 887 * <tr> 888 * <td>TV (type: 0)</td> 889 * <td>Per CEC specification.</td> 890 * <td>TV changes system volume. TV no longer reacts to incoming volume changes 891 * via {@code <User Control Pressed>}. TV no longer handles {@code <Report Audio 892 * Status>}.</td> 893 * </tr> 894 * <tr> 895 * <td>Playback device (type: 4)</td> 896 * <td>Device sends volume commands to TV/Audio system via {@code <User Control 897 * Pressed>}</td> 898 * <td>Device does not send volume commands via {@code <User Control Pressed>}.</td> 899 * </tr> 900 * <tr> 901 * <td>Audio device (type: 5)</td> 902 * <td>Full "System Audio Control" capabilities.</td> 903 * <td>Audio device no longer reacts to incoming {@code <User Control Pressed>} 904 * volume commands. Audio device no longer reports volume changes via {@code 905 * <Report Audio Status>}.</td> 906 * </tr> 907 * </table> 908 * 909 * <p> Due to the resulting behavior, usage on TV and Audio devices is discouraged. 910 * 911 * @see HdmiControlManager#setHdmiCecVolumeControlEnabled(int) 912 */ 913 public static final String CEC_SETTING_NAME_VOLUME_CONTROL_MODE = 914 "volume_control_enabled"; 915 /** 916 * Name of a setting deciding whether the TV will automatically turn on upon reception 917 * of the CEC command <Text View On> or <Image View On>. 918 * 919 * @see HdmiControlManager#setTvWakeOnOneTouchPlay(int) 920 */ 921 public static final String CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY = 922 "tv_wake_on_one_touch_play"; 923 /** 924 * Name of a setting deciding whether the TV will also turn off other CEC devices 925 * when it goes to standby mode. 926 * 927 * @see HdmiControlManager#setTvSendStandbyOnSleep(int) 928 */ 929 public static final String CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP = 930 "tv_send_standby_on_sleep"; 931 /** 932 * Name of a setting deciding whether {@code <Set Menu Language>} message should be 933 * handled by the framework or ignored. 934 * 935 * @hide 936 */ 937 public static final String CEC_SETTING_NAME_SET_MENU_LANGUAGE = "set_menu_language"; 938 /** 939 * Name of a setting representing the RC profile of a TV panel. 940 * 941 * @hide 942 */ 943 public static final String CEC_SETTING_NAME_RC_PROFILE_TV = 944 "rc_profile_tv"; 945 /** 946 * Name of a setting representing the RC profile parameter defining if a source handles the root 947 * menu. 948 * 949 * @hide 950 */ 951 public static final String CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_ROOT_MENU = 952 "rc_profile_source_handles_root_menu"; 953 /** 954 * Name of a setting representing the RC profile parameter defining if a source handles the 955 * setup menu. 956 * 957 * @hide 958 */ 959 public static final String CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_SETUP_MENU = 960 "rc_profile_source_handles_setup_menu"; 961 /** 962 * Name of a setting representing the RC profile parameter defining if a source handles the 963 * contents menu. 964 * 965 * @hide 966 */ 967 public static final String CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU = 968 "rc_profile_source_handles_contents_menu"; 969 /** 970 * Name of a setting representing the RC profile parameter defining if a source handles the top 971 * menu. 972 * 973 * @hide 974 */ 975 public static final String CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_TOP_MENU = 976 "rc_profile_source_handles_top_menu"; 977 /** 978 * Name of a setting representing the RC profile parameter defining if a source handles the 979 * media context sensitive menu. 980 * 981 * @hide 982 */ 983 public static final String 984 CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU = 985 "rc_profile_source_handles_media_context_sensitive_menu"; 986 /** 987 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the LPCM codec 988 * (0x1) should be queried or not. 989 * 990 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 991 */ 992 public static final String CEC_SETTING_NAME_QUERY_SAD_LPCM = "query_sad_lpcm"; 993 /** 994 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the DD codec 995 * (0x2) should be queried or not. 996 * 997 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 998 */ 999 public static final String CEC_SETTING_NAME_QUERY_SAD_DD = "query_sad_dd"; 1000 /** 1001 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the MPEG1 codec 1002 * (0x3) should be queried or not. 1003 * 1004 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 1005 */ 1006 public static final String CEC_SETTING_NAME_QUERY_SAD_MPEG1 = "query_sad_mpeg1"; 1007 /** 1008 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the MP3 codec 1009 * (0x4) should be queried or not. 1010 * 1011 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 1012 */ 1013 public static final String CEC_SETTING_NAME_QUERY_SAD_MP3 = "query_sad_mp3"; 1014 /** 1015 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the MPEG2 codec 1016 * (0x5) should be queried or not. 1017 * 1018 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 1019 */ 1020 public static final String CEC_SETTING_NAME_QUERY_SAD_MPEG2 = "query_sad_mpeg2"; 1021 /** 1022 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the AAC codec 1023 * (0x6) should be queried or not. 1024 * 1025 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 1026 */ 1027 public static final String CEC_SETTING_NAME_QUERY_SAD_AAC = "query_sad_aac"; 1028 /** 1029 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the DTS codec 1030 * (0x7) should be queried or not. 1031 * 1032 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 1033 */ 1034 public static final String CEC_SETTING_NAME_QUERY_SAD_DTS = "query_sad_dts"; 1035 /** 1036 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the ATRAC codec 1037 * (0x8) should be queried or not. 1038 * 1039 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 1040 */ 1041 public static final String CEC_SETTING_NAME_QUERY_SAD_ATRAC = "query_sad_atrac"; 1042 /** 1043 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the ONEBITAUDIO 1044 * codec (0x9) should be queried or not. 1045 * 1046 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 1047 */ 1048 public static final String CEC_SETTING_NAME_QUERY_SAD_ONEBITAUDIO = "query_sad_onebitaudio"; 1049 /** 1050 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the DDP codec 1051 * (0xA) should be queried or not. 1052 * 1053 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 1054 */ 1055 public static final String CEC_SETTING_NAME_QUERY_SAD_DDP = "query_sad_ddp"; 1056 /** 1057 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the DTSHD codec 1058 * (0xB) should be queried or not. 1059 * 1060 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 1061 */ 1062 public static final String CEC_SETTING_NAME_QUERY_SAD_DTSHD = "query_sad_dtshd"; 1063 /** 1064 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the TRUEHD codec 1065 * (0xC) should be queried or not. 1066 * 1067 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 1068 */ 1069 public static final String CEC_SETTING_NAME_QUERY_SAD_TRUEHD = "query_sad_truehd"; 1070 /** 1071 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the DST codec 1072 * (0xD) should be queried or not. 1073 * 1074 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 1075 */ 1076 public static final String CEC_SETTING_NAME_QUERY_SAD_DST = "query_sad_dst"; 1077 /** 1078 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the WMAPRO codec 1079 * (0xE) should be queried or not. 1080 * 1081 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 1082 */ 1083 public static final String CEC_SETTING_NAME_QUERY_SAD_WMAPRO = "query_sad_wmapro"; 1084 /** 1085 * Name of a setting representing whether the Short Audio Descriptor (SAD) for the MAX codec 1086 * (0xF) should be queried or not. 1087 * 1088 * @see HdmiControlManager#setSadPresenceInQuery(String, int) 1089 */ 1090 public static final String CEC_SETTING_NAME_QUERY_SAD_MAX = "query_sad_max"; 1091 /** 1092 * Name of a setting representing whether eARC is enabled or not. 1093 * 1094 * @see HdmiControlManager#setEarcEnabled(int) 1095 */ 1096 public static final String SETTING_NAME_EARC_ENABLED = "earc_enabled"; 1097 /** 1098 * @hide 1099 */ 1100 // TODO(b/240379115): change names of CEC settings so that their prefix matches with the other 1101 // HDMI control settings. 1102 @StringDef(value = { 1103 CEC_SETTING_NAME_HDMI_CEC_ENABLED, 1104 CEC_SETTING_NAME_HDMI_CEC_VERSION, 1105 CEC_SETTING_NAME_ROUTING_CONTROL, 1106 CEC_SETTING_NAME_SOUNDBAR_MODE, 1107 CEC_SETTING_NAME_POWER_CONTROL_MODE, 1108 CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, 1109 CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL, 1110 CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, 1111 CEC_SETTING_NAME_VOLUME_CONTROL_MODE, 1112 CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY, 1113 CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP, 1114 CEC_SETTING_NAME_SET_MENU_LANGUAGE, 1115 CEC_SETTING_NAME_RC_PROFILE_TV, 1116 CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_ROOT_MENU, 1117 CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_SETUP_MENU, 1118 CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_CONTENTS_MENU, 1119 CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_TOP_MENU, 1120 CEC_SETTING_NAME_RC_PROFILE_SOURCE_HANDLES_MEDIA_CONTEXT_SENSITIVE_MENU, 1121 CEC_SETTING_NAME_QUERY_SAD_LPCM, 1122 CEC_SETTING_NAME_QUERY_SAD_DD, 1123 CEC_SETTING_NAME_QUERY_SAD_MPEG1, 1124 CEC_SETTING_NAME_QUERY_SAD_MP3, 1125 CEC_SETTING_NAME_QUERY_SAD_MPEG2, 1126 CEC_SETTING_NAME_QUERY_SAD_AAC, 1127 CEC_SETTING_NAME_QUERY_SAD_DTS, 1128 CEC_SETTING_NAME_QUERY_SAD_ATRAC, 1129 CEC_SETTING_NAME_QUERY_SAD_ONEBITAUDIO, 1130 CEC_SETTING_NAME_QUERY_SAD_DDP, 1131 CEC_SETTING_NAME_QUERY_SAD_DTSHD, 1132 CEC_SETTING_NAME_QUERY_SAD_TRUEHD, 1133 CEC_SETTING_NAME_QUERY_SAD_DST, 1134 CEC_SETTING_NAME_QUERY_SAD_WMAPRO, 1135 CEC_SETTING_NAME_QUERY_SAD_MAX, 1136 SETTING_NAME_EARC_ENABLED, 1137 }) 1138 public @interface SettingName {} 1139 1140 /** 1141 * @hide 1142 */ 1143 @StringDef(prefix = { "CEC_SETTING_NAME_QUERY_SAD_" }, value = { 1144 CEC_SETTING_NAME_QUERY_SAD_LPCM, 1145 CEC_SETTING_NAME_QUERY_SAD_DD, 1146 CEC_SETTING_NAME_QUERY_SAD_MPEG1, 1147 CEC_SETTING_NAME_QUERY_SAD_MP3, 1148 CEC_SETTING_NAME_QUERY_SAD_MPEG2, 1149 CEC_SETTING_NAME_QUERY_SAD_AAC, 1150 CEC_SETTING_NAME_QUERY_SAD_DTS, 1151 CEC_SETTING_NAME_QUERY_SAD_ATRAC, 1152 CEC_SETTING_NAME_QUERY_SAD_ONEBITAUDIO, 1153 CEC_SETTING_NAME_QUERY_SAD_DDP, 1154 CEC_SETTING_NAME_QUERY_SAD_DTSHD, 1155 CEC_SETTING_NAME_QUERY_SAD_TRUEHD, 1156 CEC_SETTING_NAME_QUERY_SAD_DST, 1157 CEC_SETTING_NAME_QUERY_SAD_WMAPRO, 1158 CEC_SETTING_NAME_QUERY_SAD_MAX, 1159 }) 1160 public @interface CecSettingSad {} 1161 1162 // True if we have a logical device of type playback hosted in the system. 1163 private final boolean mHasPlaybackDevice; 1164 // True if we have a logical device of type TV hosted in the system. 1165 private final boolean mHasTvDevice; 1166 // True if we have a logical device of type audio system hosted in the system. 1167 private final boolean mHasAudioSystemDevice; 1168 // True if we have a logical device of type audio system hosted in the system. 1169 private final boolean mHasSwitchDevice; 1170 // True if it's a switch device. 1171 private final boolean mIsSwitchDevice; 1172 1173 /** 1174 * {@hide} - hide this constructor because it has a parameter of type IHdmiControlService, 1175 * which is a system private class. The right way to create an instance of this class is 1176 * using the factory Context.getSystemService. 1177 */ HdmiControlManager(IHdmiControlService service)1178 public HdmiControlManager(IHdmiControlService service) { 1179 mService = service; 1180 int[] types = null; 1181 if (mService != null) { 1182 try { 1183 types = mService.getSupportedTypes(); 1184 } catch (RemoteException e) { 1185 throw e.rethrowFromSystemServer(); 1186 } 1187 } 1188 mHasTvDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_TV); 1189 mHasPlaybackDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_PLAYBACK); 1190 mHasAudioSystemDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); 1191 mHasSwitchDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH); 1192 mIsSwitchDevice = HdmiProperties.is_switch().orElse(false); 1193 addHotplugEventListener(new ClientHotplugEventListener()); 1194 } 1195 1196 private final class ClientHotplugEventListener implements HotplugEventListener { 1197 1198 @Override onReceived(HdmiHotplugEvent event)1199 public void onReceived(HdmiHotplugEvent event) { 1200 List<HdmiPortInfo> ports = new ArrayList<>(); 1201 try { 1202 ports = mService.getPortInfo(); 1203 } catch (RemoteException e) { 1204 throw e.rethrowFromSystemServer(); 1205 } 1206 if (ports.isEmpty()) { 1207 Log.e(TAG, "Can't find port info, not updating connected status. " 1208 + "Hotplug event:" + event); 1209 return; 1210 } 1211 // If the HDMI OUT port is plugged or unplugged, update the mLocalPhysicalAddress 1212 for (HdmiPortInfo port : ports) { 1213 if (port.getId() == event.getPort()) { 1214 if (port.getType() == HdmiPortInfo.PORT_OUTPUT) { 1215 setLocalPhysicalAddress( 1216 event.isConnected() 1217 ? port.getAddress() 1218 : INVALID_PHYSICAL_ADDRESS); 1219 } 1220 break; 1221 } 1222 } 1223 } 1224 } 1225 hasDeviceType(int[] types, int type)1226 private static boolean hasDeviceType(int[] types, int type) { 1227 if (types == null) { 1228 return false; 1229 } 1230 for (int t : types) { 1231 if (t == type) { 1232 return true; 1233 } 1234 } 1235 return false; 1236 } 1237 1238 /** 1239 * Gets an object that represents an HDMI-CEC logical device of a specified type. 1240 * 1241 * @param type CEC device type 1242 * @return {@link HdmiClient} instance. {@code null} on failure. 1243 * See {@link HdmiDeviceInfo#DEVICE_PLAYBACK} 1244 * See {@link HdmiDeviceInfo#DEVICE_TV} 1245 * See {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM} 1246 */ 1247 @Nullable 1248 @SuppressLint("RequiresPermission") getClient(int type)1249 public HdmiClient getClient(int type) { 1250 if (mService == null) { 1251 return null; 1252 } 1253 switch (type) { 1254 case HdmiDeviceInfo.DEVICE_TV: 1255 return mHasTvDevice ? new HdmiTvClient(mService) : null; 1256 case HdmiDeviceInfo.DEVICE_PLAYBACK: 1257 return mHasPlaybackDevice ? new HdmiPlaybackClient(mService) : null; 1258 case HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM: 1259 try { 1260 if ((mService.getCecSettingIntValue(CEC_SETTING_NAME_SOUNDBAR_MODE) 1261 == SOUNDBAR_MODE_ENABLED && mHasPlaybackDevice) 1262 || mHasAudioSystemDevice) { 1263 return new HdmiAudioSystemClient(mService); 1264 } 1265 } catch (RemoteException e) { 1266 throw e.rethrowFromSystemServer(); 1267 } 1268 return null; 1269 case HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH: 1270 return (mHasSwitchDevice || mIsSwitchDevice) 1271 ? new HdmiSwitchClient(mService) : null; 1272 default: 1273 return null; 1274 } 1275 } 1276 1277 /** 1278 * Gets an object that represents an HDMI-CEC logical device of type playback on the system. 1279 * 1280 * <p>Used to send HDMI control messages to other devices like TV or audio amplifier through 1281 * HDMI bus. It is also possible to communicate with other logical devices hosted in the same 1282 * system if the system is configured to host more than one type of HDMI-CEC logical devices. 1283 * 1284 * @return {@link HdmiPlaybackClient} instance. {@code null} on failure. 1285 */ 1286 @Nullable 1287 @SuppressLint("RequiresPermission") getPlaybackClient()1288 public HdmiPlaybackClient getPlaybackClient() { 1289 return (HdmiPlaybackClient) getClient(HdmiDeviceInfo.DEVICE_PLAYBACK); 1290 } 1291 1292 /** 1293 * Gets an object that represents an HDMI-CEC logical device of type TV on the system. 1294 * 1295 * <p>Used to send HDMI control messages to other devices and manage them through 1296 * HDMI bus. It is also possible to communicate with other logical devices hosted in the same 1297 * system if the system is configured to host more than one type of HDMI-CEC logical devices. 1298 * 1299 * @return {@link HdmiTvClient} instance. {@code null} on failure. 1300 */ 1301 @Nullable 1302 @SuppressLint("RequiresPermission") getTvClient()1303 public HdmiTvClient getTvClient() { 1304 return (HdmiTvClient) getClient(HdmiDeviceInfo.DEVICE_TV); 1305 } 1306 1307 /** 1308 * Gets an object that represents an HDMI-CEC logical device of type audio system on the system. 1309 * 1310 * <p>Used to send HDMI control messages to other devices like TV through HDMI bus. It is also 1311 * possible to communicate with other logical devices hosted in the same system if the system is 1312 * configured to host more than one type of HDMI-CEC logical devices. 1313 * 1314 * @return {@link HdmiAudioSystemClient} instance. {@code null} on failure. 1315 * 1316 * @hide 1317 */ 1318 @Nullable 1319 @SuppressLint("RequiresPermission") getAudioSystemClient()1320 public HdmiAudioSystemClient getAudioSystemClient() { 1321 return (HdmiAudioSystemClient) getClient(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); 1322 } 1323 1324 /** 1325 * Gets an object that represents an HDMI-CEC logical device of type switch on the system. 1326 * 1327 * <p>Used to send HDMI control messages to other devices (e.g. TVs) through HDMI bus. 1328 * It is also possible to communicate with other logical devices hosted in the same 1329 * system if the system is configured to host more than one type of HDMI-CEC logical device. 1330 * 1331 * @return {@link HdmiSwitchClient} instance. {@code null} on failure. 1332 */ 1333 @Nullable 1334 @SuppressLint("RequiresPermission") getSwitchClient()1335 public HdmiSwitchClient getSwitchClient() { 1336 return (HdmiSwitchClient) getClient(HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH); 1337 } 1338 1339 /** 1340 * Get a snapshot of the real-time status of the devices on the CEC bus. 1341 * 1342 * <p>This only applies to devices with switch functionality, which are devices with one 1343 * or more than one HDMI inputs. 1344 * 1345 * @return a list of {@link HdmiDeviceInfo} of the connected CEC devices on the CEC bus. An 1346 * empty list will be returned if there is none. 1347 */ 1348 @NonNull getConnectedDevices()1349 public List<HdmiDeviceInfo> getConnectedDevices() { 1350 try { 1351 return mService.getDeviceList(); 1352 } catch (RemoteException e) { 1353 throw e.rethrowFromSystemServer(); 1354 } 1355 } 1356 1357 /** 1358 * @removed 1359 * @deprecated Please use {@link #getConnectedDevices()} instead. 1360 */ 1361 @Deprecated getConnectedDevicesList()1362 public List<HdmiDeviceInfo> getConnectedDevicesList() { 1363 try { 1364 return mService.getDeviceList(); 1365 } catch (RemoteException e) { 1366 throw e.rethrowFromSystemServer(); 1367 } 1368 } 1369 1370 /** 1371 * Get the list of the HDMI ports configuration. 1372 * 1373 * <p>This returns an empty list when the current device does not have HDMI ports. 1374 * 1375 * @return a list of {@link HdmiPortInfo} 1376 */ 1377 @NonNull getPortInfo()1378 public List<HdmiPortInfo> getPortInfo() { 1379 try { 1380 return mService.getPortInfo(); 1381 } catch (RemoteException e) { 1382 throw e.rethrowFromSystemServer(); 1383 } 1384 } 1385 1386 /** 1387 * Power off the target device by sending CEC commands. Note that this device can't be the 1388 * current device itself. 1389 * 1390 * <p>The target device info can be obtained by calling {@link #getConnectedDevicesList()}. 1391 * 1392 * @param deviceInfo {@link HdmiDeviceInfo} of the device to be powered off. 1393 */ powerOffDevice(@onNull HdmiDeviceInfo deviceInfo)1394 public void powerOffDevice(@NonNull HdmiDeviceInfo deviceInfo) { 1395 Objects.requireNonNull(deviceInfo); 1396 try { 1397 mService.powerOffRemoteDevice( 1398 deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus()); 1399 } catch (RemoteException e) { 1400 throw e.rethrowFromSystemServer(); 1401 } 1402 } 1403 1404 /** 1405 * @removed 1406 * @deprecated Please use {@link #powerOffDevice(deviceInfo)} instead. 1407 */ 1408 @Deprecated powerOffRemoteDevice(@onNull HdmiDeviceInfo deviceInfo)1409 public void powerOffRemoteDevice(@NonNull HdmiDeviceInfo deviceInfo) { 1410 Objects.requireNonNull(deviceInfo); 1411 try { 1412 mService.powerOffRemoteDevice( 1413 deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus()); 1414 } catch (RemoteException e) { 1415 throw e.rethrowFromSystemServer(); 1416 } 1417 } 1418 1419 /** 1420 * Power on the target device by sending CEC commands. Note that this device can't be the 1421 * current device itself. 1422 * 1423 * <p>The target device info can be obtained by calling {@link #getConnectedDevicesList()}. 1424 * 1425 * @param deviceInfo {@link HdmiDeviceInfo} of the device to be powered on. 1426 * 1427 * @hide 1428 */ powerOnDevice(HdmiDeviceInfo deviceInfo)1429 public void powerOnDevice(HdmiDeviceInfo deviceInfo) { 1430 Objects.requireNonNull(deviceInfo); 1431 try { 1432 mService.powerOnRemoteDevice( 1433 deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus()); 1434 } catch (RemoteException e) { 1435 throw e.rethrowFromSystemServer(); 1436 } 1437 } 1438 1439 /** 1440 * @removed 1441 * @deprecated Please use {@link #powerOnDevice(deviceInfo)} instead. 1442 */ 1443 @Deprecated powerOnRemoteDevice(HdmiDeviceInfo deviceInfo)1444 public void powerOnRemoteDevice(HdmiDeviceInfo deviceInfo) { 1445 Objects.requireNonNull(deviceInfo); 1446 try { 1447 mService.powerOnRemoteDevice( 1448 deviceInfo.getLogicalAddress(), deviceInfo.getDevicePowerStatus()); 1449 } catch (RemoteException e) { 1450 throw e.rethrowFromSystemServer(); 1451 } 1452 } 1453 1454 /** 1455 * Request the target device to be the new Active Source by sending CEC commands. Note that 1456 * this device can't be the current device itself. 1457 * 1458 * <p>The target device info can be obtained by calling {@link #getConnectedDevicesList()}. 1459 * 1460 * <p>If the target device responds to the command, the users should see the target device 1461 * streaming on their TVs. 1462 * 1463 * @param deviceInfo HdmiDeviceInfo of the target device 1464 */ setActiveSource(@onNull HdmiDeviceInfo deviceInfo)1465 public void setActiveSource(@NonNull HdmiDeviceInfo deviceInfo) { 1466 Objects.requireNonNull(deviceInfo); 1467 try { 1468 mService.askRemoteDeviceToBecomeActiveSource(deviceInfo.getPhysicalAddress()); 1469 } catch (RemoteException e) { 1470 throw e.rethrowFromSystemServer(); 1471 } 1472 } 1473 1474 /** 1475 * @removed 1476 * @deprecated Please use {@link #setActiveSource(deviceInfo)} instead. 1477 */ 1478 @Deprecated requestRemoteDeviceToBecomeActiveSource(@onNull HdmiDeviceInfo deviceInfo)1479 public void requestRemoteDeviceToBecomeActiveSource(@NonNull HdmiDeviceInfo deviceInfo) { 1480 Objects.requireNonNull(deviceInfo); 1481 try { 1482 mService.askRemoteDeviceToBecomeActiveSource(deviceInfo.getPhysicalAddress()); 1483 } catch (RemoteException e) { 1484 throw e.rethrowFromSystemServer(); 1485 } 1486 } 1487 1488 /** 1489 * Controls standby mode of the system. It will also try to turn on/off the connected devices if 1490 * necessary. 1491 * 1492 * @param isStandbyModeOn target status of the system's standby mode 1493 */ 1494 @RequiresPermission(android.Manifest.permission.HDMI_CEC) setStandbyMode(boolean isStandbyModeOn)1495 public void setStandbyMode(boolean isStandbyModeOn) { 1496 try { 1497 mService.setStandbyMode(isStandbyModeOn); 1498 } catch (RemoteException e) { 1499 throw e.rethrowFromSystemServer(); 1500 } 1501 } 1502 1503 /** 1504 * For CEC source devices (OTT/STB/Audio system): toggle the power status of the HDMI-connected 1505 * display and follow the display's new power status. 1506 * For all other devices: no functionality. 1507 * 1508 * @hide 1509 */ 1510 @RequiresPermission(android.Manifest.permission.HDMI_CEC) toggleAndFollowTvPower()1511 public void toggleAndFollowTvPower() { 1512 try { 1513 mService.toggleAndFollowTvPower(); 1514 } catch (RemoteException e) { 1515 throw e.rethrowFromSystemServer(); 1516 } 1517 } 1518 1519 /** 1520 * Determines whether the HDMI CEC stack should handle KEYCODE_TV_POWER. 1521 * 1522 * @hide 1523 */ 1524 @RequiresPermission(android.Manifest.permission.HDMI_CEC) shouldHandleTvPowerKey()1525 public boolean shouldHandleTvPowerKey() { 1526 try { 1527 return mService.shouldHandleTvPowerKey(); 1528 } catch (RemoteException e) { 1529 throw e.rethrowFromSystemServer(); 1530 } 1531 } 1532 1533 /** 1534 * Controls whether volume control commands via HDMI CEC are enabled. 1535 * 1536 * <p>When disabled: 1537 * <ul> 1538 * <li>the device will not send any HDMI CEC audio messages 1539 * <li>received HDMI CEC audio messages are responded to with {@code <Feature Abort>} 1540 * </ul> 1541 * 1542 * <p>Effects on different device types: 1543 * <table> 1544 * <tr><th>HDMI CEC device type</th><th>enabled</th><th>disabled</th></tr> 1545 * <tr> 1546 * <td>TV (type: 0)</td> 1547 * <td>Per CEC specification.</td> 1548 * <td>TV changes system volume. TV no longer reacts to incoming volume changes via 1549 * {@code <User Control Pressed>}. TV no longer handles {@code <Report Audio Status>} 1550 * .</td> 1551 * </tr> 1552 * <tr> 1553 * <td>Playback device (type: 4)</td> 1554 * <td>Device sends volume commands to TV/Audio system via {@code <User Control 1555 * Pressed>}</td><td>Device does not send volume commands via {@code <User Control 1556 * Pressed>}.</td> 1557 * </tr> 1558 * <tr> 1559 * <td>Audio device (type: 5)</td> 1560 * <td>Full "System Audio Control" capabilities.</td> 1561 * <td>Audio device no longer reacts to incoming {@code <User Control Pressed>} 1562 * volume commands. Audio device no longer reports volume changes via {@code <Report 1563 * Audio Status>}.</td> 1564 * </tr> 1565 * </table> 1566 * 1567 * <p> Due to the resulting behavior, usage on TV and Audio devices is discouraged. 1568 * 1569 * @param hdmiCecVolumeControlEnabled target state of HDMI CEC volume control. 1570 * @see HdmiControlManager#CEC_SETTING_NAME_VOLUME_CONTROL_MODE 1571 */ 1572 @RequiresPermission(android.Manifest.permission.HDMI_CEC) setHdmiCecVolumeControlEnabled( @olumeControl int hdmiCecVolumeControlEnabled)1573 public void setHdmiCecVolumeControlEnabled( 1574 @VolumeControl int hdmiCecVolumeControlEnabled) { 1575 try { 1576 mService.setCecSettingIntValue(CEC_SETTING_NAME_VOLUME_CONTROL_MODE, 1577 hdmiCecVolumeControlEnabled); 1578 } catch (RemoteException e) { 1579 throw e.rethrowFromSystemServer(); 1580 } 1581 } 1582 1583 /** 1584 * Returns whether volume changes via HDMI CEC are enabled. 1585 * 1586 * @see HdmiControlManager#CEC_SETTING_NAME_VOLUME_CONTROL_MODE 1587 */ 1588 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 1589 @VolumeControl getHdmiCecVolumeControlEnabled()1590 public int getHdmiCecVolumeControlEnabled() { 1591 try { 1592 return mService.getCecSettingIntValue(CEC_SETTING_NAME_VOLUME_CONTROL_MODE); 1593 } catch (RemoteException e) { 1594 throw e.rethrowFromSystemServer(); 1595 } 1596 } 1597 1598 /** 1599 * Gets whether the system is in system audio mode. 1600 * 1601 * @hide 1602 */ getSystemAudioMode()1603 public boolean getSystemAudioMode() { 1604 try { 1605 return mService.getSystemAudioMode(); 1606 } catch (RemoteException e) { 1607 throw e.rethrowFromSystemServer(); 1608 } 1609 } 1610 1611 /** 1612 * Get the physical address of the device. 1613 * 1614 * <p>Physical address needs to be automatically adjusted when devices are phyiscally or 1615 * electrically added or removed from the device tree. Please see HDMI Specification Version 1616 * 1.4b 8.7 Physical Address for more details on the address discovery proccess. 1617 */ getPhysicalAddress()1618 public int getPhysicalAddress() { 1619 return getLocalPhysicalAddress(); 1620 } 1621 1622 /** 1623 * Check if the target device is connected to the current device. 1624 * 1625 * <p>The API also returns true if the current device is the target. 1626 * 1627 * @param targetDevice {@link HdmiDeviceInfo} of the target device. 1628 * @return true if {@code targetDevice} is directly or indirectly 1629 * connected to the current device. 1630 */ isDeviceConnected(@onNull HdmiDeviceInfo targetDevice)1631 public boolean isDeviceConnected(@NonNull HdmiDeviceInfo targetDevice) { 1632 Objects.requireNonNull(targetDevice); 1633 int physicalAddress = getLocalPhysicalAddress(); 1634 if (physicalAddress == INVALID_PHYSICAL_ADDRESS) { 1635 return false; 1636 } 1637 int targetPhysicalAddress = targetDevice.getPhysicalAddress(); 1638 if (targetPhysicalAddress == INVALID_PHYSICAL_ADDRESS) { 1639 return false; 1640 } 1641 return HdmiUtils.getLocalPortFromPhysicalAddress(targetPhysicalAddress, physicalAddress) 1642 != HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE; 1643 } 1644 1645 /** 1646 * @removed 1647 * @deprecated Please use {@link #isDeviceConnected(targetDevice)} instead. 1648 */ 1649 @Deprecated isRemoteDeviceConnected(@onNull HdmiDeviceInfo targetDevice)1650 public boolean isRemoteDeviceConnected(@NonNull HdmiDeviceInfo targetDevice) { 1651 Objects.requireNonNull(targetDevice); 1652 int physicalAddress = getLocalPhysicalAddress(); 1653 if (physicalAddress == INVALID_PHYSICAL_ADDRESS) { 1654 return false; 1655 } 1656 int targetPhysicalAddress = targetDevice.getPhysicalAddress(); 1657 if (targetPhysicalAddress == INVALID_PHYSICAL_ADDRESS) { 1658 return false; 1659 } 1660 return HdmiUtils.getLocalPortFromPhysicalAddress(targetPhysicalAddress, physicalAddress) 1661 != HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE; 1662 } 1663 1664 /** 1665 * Listener used to get hotplug event from HDMI port. 1666 */ 1667 public interface HotplugEventListener { onReceived(HdmiHotplugEvent event)1668 void onReceived(HdmiHotplugEvent event); 1669 } 1670 1671 private final ArrayMap<HotplugEventListener, IHdmiHotplugEventListener> 1672 mHotplugEventListeners = new ArrayMap<>(); 1673 1674 /** 1675 * Listener used to get HDMI Control (CEC) status (enabled/disabled) and the connected display 1676 * status. 1677 * @hide 1678 */ 1679 public interface HdmiControlStatusChangeListener { 1680 /** 1681 * Called when HDMI Control (CEC) is enabled/disabled. 1682 * 1683 * @param isCecEnabled status of HDMI Control 1684 * {@link android.hardware.hdmi.HdmiControlManager#CEC_SETTING_NAME_HDMI_CEC_ENABLED}: 1685 * {@code HDMI_CEC_CONTROL_ENABLED} if enabled. 1686 * @param isCecAvailable status of CEC support of the connected display (the TV). 1687 * {@code true} if supported. 1688 * 1689 * Note: Value of isCecAvailable is only valid when isCecEnabled is true. 1690 **/ onStatusChange(@dmiControlManager.HdmiCecControl int isCecEnabled, boolean isCecAvailable)1691 void onStatusChange(@HdmiControlManager.HdmiCecControl int isCecEnabled, 1692 boolean isCecAvailable); 1693 } 1694 1695 private final ArrayMap<HdmiControlStatusChangeListener, IHdmiControlStatusChangeListener> 1696 mHdmiControlStatusChangeListeners = new ArrayMap<>(); 1697 1698 /** 1699 * Listener used to get the status of the HDMI CEC volume control feature (enabled/disabled). 1700 * @hide 1701 */ 1702 public interface HdmiCecVolumeControlFeatureListener { 1703 /** 1704 * Called when the HDMI Control (CEC) volume control feature is enabled/disabled. 1705 * 1706 * @param hdmiCecVolumeControl status of HDMI CEC volume control feature 1707 * @see {@link HdmiControlManager#setHdmiCecVolumeControlEnabled(int)} ()} 1708 **/ onHdmiCecVolumeControlFeature(@olumeControl int hdmiCecVolumeControl)1709 void onHdmiCecVolumeControlFeature(@VolumeControl int hdmiCecVolumeControl); 1710 } 1711 1712 private final ArrayMap<HdmiCecVolumeControlFeatureListener, 1713 IHdmiCecVolumeControlFeatureListener> 1714 mHdmiCecVolumeControlFeatureListeners = new ArrayMap<>(); 1715 1716 /** 1717 * Listener used to get vendor-specific commands. 1718 */ 1719 public interface VendorCommandListener { 1720 /** 1721 * Called when a vendor command is received. 1722 * 1723 * @param srcAddress source logical address 1724 * @param destAddress destination logical address 1725 * @param params vendor-specific parameters 1726 * @param hasVendorId {@code true} if the command is <Vendor Command 1727 * With ID>. The first 3 bytes of params is vendor id. 1728 */ onReceived(int srcAddress, int destAddress, byte[] params, boolean hasVendorId)1729 void onReceived(int srcAddress, int destAddress, byte[] params, boolean hasVendorId); 1730 1731 /** 1732 * The callback is called: 1733 * <ul> 1734 * <li> before HdmiControlService is disabled. 1735 * <li> after HdmiControlService is enabled and the local address is assigned. 1736 * </ul> 1737 * The client shouldn't hold the thread too long since this is a blocking call. 1738 * 1739 * @param enabled {@code true} if HdmiControlService is enabled. 1740 * @param reason the reason code why the state of HdmiControlService is changed. 1741 * @see #CONTROL_STATE_CHANGED_REASON_START 1742 * @see #CONTROL_STATE_CHANGED_REASON_SETTING 1743 * @see #CONTROL_STATE_CHANGED_REASON_WAKEUP 1744 * @see #CONTROL_STATE_CHANGED_REASON_STANDBY 1745 */ onControlStateChanged(boolean enabled, int reason)1746 void onControlStateChanged(boolean enabled, int reason); 1747 } 1748 1749 /** 1750 * Adds a listener to get informed of {@link HdmiHotplugEvent}. 1751 * 1752 * <p>To stop getting the notification, 1753 * use {@link #removeHotplugEventListener(HotplugEventListener)}. 1754 * 1755 * Note that each invocation of the callback will be executed on an arbitrary 1756 * Binder thread. This means that all callback implementations must be 1757 * thread safe. To specify the execution thread, use 1758 * {@link addHotplugEventListener(Executor, HotplugEventListener)}. 1759 * 1760 * @param listener {@link HotplugEventListener} instance 1761 * @see HdmiControlManager#removeHotplugEventListener(HotplugEventListener) 1762 */ 1763 @RequiresPermission(android.Manifest.permission.HDMI_CEC) addHotplugEventListener(HotplugEventListener listener)1764 public void addHotplugEventListener(HotplugEventListener listener) { 1765 addHotplugEventListener(ConcurrentUtils.DIRECT_EXECUTOR, listener); 1766 } 1767 1768 /** 1769 * Adds a listener to get informed of {@link HdmiHotplugEvent}. 1770 * 1771 * <p>To stop getting the notification, 1772 * use {@link #removeHotplugEventListener(HotplugEventListener)}. 1773 * 1774 * @param listener {@link HotplugEventListener} instance 1775 * @see HdmiControlManager#removeHotplugEventListener(HotplugEventListener) 1776 */ 1777 @RequiresPermission(android.Manifest.permission.HDMI_CEC) addHotplugEventListener(@onNull @allbackExecutor Executor executor, @NonNull HotplugEventListener listener)1778 public void addHotplugEventListener(@NonNull @CallbackExecutor Executor executor, 1779 @NonNull HotplugEventListener listener) { 1780 if (mService == null) { 1781 Log.e(TAG, "addHotplugEventListener: HdmiControlService is not available"); 1782 return; 1783 } 1784 if (mHotplugEventListeners.containsKey(listener)) { 1785 Log.e(TAG, "listener is already registered"); 1786 return; 1787 } 1788 IHdmiHotplugEventListener wrappedListener = 1789 getHotplugEventListenerWrapper(executor, listener); 1790 mHotplugEventListeners.put(listener, wrappedListener); 1791 try { 1792 mService.addHotplugEventListener(wrappedListener); 1793 } catch (RemoteException e) { 1794 throw e.rethrowFromSystemServer(); 1795 } 1796 } 1797 1798 /** 1799 * Removes a listener to stop getting informed of {@link HdmiHotplugEvent}. 1800 * 1801 * @param listener {@link HotplugEventListener} instance to be removed 1802 */ 1803 @RequiresPermission(android.Manifest.permission.HDMI_CEC) removeHotplugEventListener(HotplugEventListener listener)1804 public void removeHotplugEventListener(HotplugEventListener listener) { 1805 if (mService == null) { 1806 Log.e(TAG, "removeHotplugEventListener: HdmiControlService is not available"); 1807 return; 1808 } 1809 IHdmiHotplugEventListener wrappedListener = mHotplugEventListeners.remove(listener); 1810 if (wrappedListener == null) { 1811 Log.e(TAG, "tried to remove not-registered listener"); 1812 return; 1813 } 1814 try { 1815 mService.removeHotplugEventListener(wrappedListener); 1816 } catch (RemoteException e) { 1817 throw e.rethrowFromSystemServer(); 1818 } 1819 } 1820 getHotplugEventListenerWrapper( Executor executor, final HotplugEventListener listener)1821 private IHdmiHotplugEventListener getHotplugEventListenerWrapper( 1822 Executor executor, final HotplugEventListener listener) { 1823 return new IHdmiHotplugEventListener.Stub() { 1824 @Override 1825 public void onReceived(HdmiHotplugEvent event) { 1826 final long token = Binder.clearCallingIdentity(); 1827 try { 1828 executor.execute(() -> listener.onReceived(event)); 1829 } finally { 1830 Binder.restoreCallingIdentity(token); 1831 } 1832 } 1833 }; 1834 } 1835 1836 /** 1837 * Adds a listener to get informed of {@link HdmiControlStatusChange}. 1838 * 1839 * <p>To stop getting the notification, 1840 * use {@link #removeHdmiControlStatusChangeListener(HdmiControlStatusChangeListener)}. 1841 * 1842 * Note that each invocation of the callback will be executed on an arbitrary 1843 * Binder thread. This means that all callback implementations must be 1844 * thread safe. To specify the execution thread, use 1845 * {@link addHdmiControlStatusChangeListener(Executor, HdmiControlStatusChangeListener)}. 1846 * 1847 * @param listener {@link HdmiControlStatusChangeListener} instance 1848 * @see HdmiControlManager#removeHdmiControlStatusChangeListener( 1849 * HdmiControlStatusChangeListener) 1850 * 1851 * @hide 1852 */ 1853 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 1854 public void addHdmiControlStatusChangeListener(HdmiControlStatusChangeListener listener) { 1855 addHdmiControlStatusChangeListener(ConcurrentUtils.DIRECT_EXECUTOR, listener); 1856 } 1857 1858 /** 1859 * Adds a listener to get informed of {@link HdmiControlStatusChange}. 1860 * 1861 * <p>To stop getting the notification, 1862 * use {@link #removeHdmiControlStatusChangeListener(HdmiControlStatusChangeListener)}. 1863 * 1864 * @param listener {@link HdmiControlStatusChangeListener} instance 1865 * @see HdmiControlManager#removeHdmiControlStatusChangeListener( 1866 * HdmiControlStatusChangeListener) 1867 * 1868 * @hide 1869 */ 1870 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 1871 public void addHdmiControlStatusChangeListener(@NonNull @CallbackExecutor Executor executor, 1872 @NonNull HdmiControlStatusChangeListener listener) { 1873 if (mService == null) { 1874 Log.e(TAG, "addHdmiControlStatusChangeListener: HdmiControlService is not available"); 1875 return; 1876 } 1877 if (mHdmiControlStatusChangeListeners.containsKey(listener)) { 1878 Log.e(TAG, "listener is already registered"); 1879 return; 1880 } 1881 IHdmiControlStatusChangeListener wrappedListener = 1882 getHdmiControlStatusChangeListenerWrapper(executor, listener); 1883 mHdmiControlStatusChangeListeners.put(listener, wrappedListener); 1884 try { 1885 mService.addHdmiControlStatusChangeListener(wrappedListener); 1886 } catch (RemoteException e) { 1887 throw e.rethrowFromSystemServer(); 1888 } 1889 } 1890 1891 /** 1892 * Removes a listener to stop getting informed of {@link HdmiControlStatusChange}. 1893 * 1894 * @param listener {@link HdmiControlStatusChangeListener} instance to be removed 1895 * 1896 * @hide 1897 */ 1898 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 1899 public void removeHdmiControlStatusChangeListener(HdmiControlStatusChangeListener listener) { 1900 if (mService == null) { 1901 Log.e(TAG, 1902 "removeHdmiControlStatusChangeListener: HdmiControlService is not available"); 1903 return; 1904 } 1905 IHdmiControlStatusChangeListener wrappedListener = 1906 mHdmiControlStatusChangeListeners.remove(listener); 1907 if (wrappedListener == null) { 1908 Log.e(TAG, "tried to remove not-registered listener"); 1909 return; 1910 } 1911 try { 1912 mService.removeHdmiControlStatusChangeListener(wrappedListener); 1913 } catch (RemoteException e) { 1914 throw e.rethrowFromSystemServer(); 1915 } 1916 } 1917 1918 private IHdmiControlStatusChangeListener getHdmiControlStatusChangeListenerWrapper( 1919 Executor executor, final HdmiControlStatusChangeListener listener) { 1920 return new IHdmiControlStatusChangeListener.Stub() { 1921 @Override 1922 public void onStatusChange(@HdmiCecControl int isCecEnabled, boolean isCecAvailable) { 1923 final long token = Binder.clearCallingIdentity(); 1924 try { 1925 executor.execute(() -> listener.onStatusChange(isCecEnabled, isCecAvailable)); 1926 } finally { 1927 Binder.restoreCallingIdentity(token); 1928 } 1929 } 1930 }; 1931 } 1932 1933 /** 1934 * Adds a listener to get informed of changes to the state of the HDMI CEC volume control 1935 * feature. 1936 * 1937 * Upon adding a listener, the current state of the HDMI CEC volume control feature will be 1938 * sent immediately. 1939 * 1940 * <p>To stop getting the notification, 1941 * use {@link #removeHdmiCecVolumeControlFeatureListener(HdmiCecVolumeControlFeatureListener)}. 1942 * 1943 * @param listener {@link HdmiCecVolumeControlFeatureListener} instance 1944 * @hide 1945 * @see #removeHdmiCecVolumeControlFeatureListener(HdmiCecVolumeControlFeatureListener) 1946 */ 1947 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 1948 public void addHdmiCecVolumeControlFeatureListener(@NonNull @CallbackExecutor Executor executor, 1949 @NonNull HdmiCecVolumeControlFeatureListener listener) { 1950 if (mService == null) { 1951 Log.e(TAG, 1952 "addHdmiCecVolumeControlFeatureListener: HdmiControlService is not available"); 1953 return; 1954 } 1955 if (mHdmiCecVolumeControlFeatureListeners.containsKey(listener)) { 1956 Log.e(TAG, "listener is already registered"); 1957 return; 1958 } 1959 IHdmiCecVolumeControlFeatureListener wrappedListener = 1960 createHdmiCecVolumeControlFeatureListenerWrapper(executor, listener); 1961 mHdmiCecVolumeControlFeatureListeners.put(listener, wrappedListener); 1962 try { 1963 mService.addHdmiCecVolumeControlFeatureListener(wrappedListener); 1964 } catch (RemoteException e) { 1965 throw e.rethrowFromSystemServer(); 1966 } 1967 } 1968 1969 /** 1970 * Removes a listener to stop getting informed of changes to the state of the HDMI CEC volume 1971 * control feature. 1972 * 1973 * @param listener {@link HdmiCecVolumeControlFeatureListener} instance to be removed 1974 * @hide 1975 */ 1976 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 1977 public void removeHdmiCecVolumeControlFeatureListener( 1978 HdmiCecVolumeControlFeatureListener listener) { 1979 if (mService == null) { 1980 Log.e(TAG, 1981 "removeHdmiCecVolumeControlFeatureListener: HdmiControlService is not " 1982 + "available"); 1983 return; 1984 } 1985 IHdmiCecVolumeControlFeatureListener wrappedListener = 1986 mHdmiCecVolumeControlFeatureListeners.remove(listener); 1987 if (wrappedListener == null) { 1988 Log.e(TAG, "tried to remove not-registered listener"); 1989 return; 1990 } 1991 try { 1992 mService.removeHdmiCecVolumeControlFeatureListener(wrappedListener); 1993 } catch (RemoteException e) { 1994 throw e.rethrowFromSystemServer(); 1995 } 1996 } 1997 1998 private IHdmiCecVolumeControlFeatureListener createHdmiCecVolumeControlFeatureListenerWrapper( 1999 Executor executor, final HdmiCecVolumeControlFeatureListener listener) { 2000 return new android.hardware.hdmi.IHdmiCecVolumeControlFeatureListener.Stub() { 2001 @Override 2002 public void onHdmiCecVolumeControlFeature(int enabled) { 2003 final long token = Binder.clearCallingIdentity(); 2004 try { 2005 executor.execute(() -> listener.onHdmiCecVolumeControlFeature(enabled)); 2006 } finally { 2007 Binder.restoreCallingIdentity(token); 2008 } 2009 } 2010 }; 2011 } 2012 2013 /** 2014 * Listener used to get setting change notification. 2015 */ 2016 public interface CecSettingChangeListener { 2017 /** 2018 * Called when value of a setting changes. 2019 * 2020 * @param setting name of a CEC setting that changed 2021 */ 2022 void onChange(@NonNull @SettingName String setting); 2023 } 2024 2025 private final ArrayMap<String, 2026 ArrayMap<CecSettingChangeListener, IHdmiCecSettingChangeListener>> 2027 mCecSettingChangeListeners = new ArrayMap<>(); 2028 2029 private void addCecSettingChangeListener( 2030 @NonNull @SettingName String setting, 2031 @NonNull @CallbackExecutor Executor executor, 2032 @NonNull CecSettingChangeListener listener) { 2033 if (mService == null) { 2034 Log.e(TAG, "addCecSettingChangeListener: HdmiControlService is not available"); 2035 return; 2036 } 2037 if (mCecSettingChangeListeners.containsKey(setting) 2038 && mCecSettingChangeListeners.get(setting).containsKey(listener)) { 2039 Log.e(TAG, "listener is already registered"); 2040 return; 2041 } 2042 IHdmiCecSettingChangeListener wrappedListener = 2043 getCecSettingChangeListenerWrapper(executor, listener); 2044 if (!mCecSettingChangeListeners.containsKey(setting)) { 2045 mCecSettingChangeListeners.put(setting, new ArrayMap<>()); 2046 } 2047 mCecSettingChangeListeners.get(setting).put(listener, wrappedListener); 2048 try { 2049 mService.addCecSettingChangeListener(setting, wrappedListener); 2050 } catch (RemoteException e) { 2051 throw e.rethrowFromSystemServer(); 2052 } 2053 } 2054 2055 private void removeCecSettingChangeListener( 2056 @NonNull @SettingName String setting, 2057 @NonNull CecSettingChangeListener listener) { 2058 if (mService == null) { 2059 Log.e(TAG, "removeCecSettingChangeListener: HdmiControlService is not available"); 2060 return; 2061 } 2062 IHdmiCecSettingChangeListener wrappedListener = 2063 !mCecSettingChangeListeners.containsKey(setting) ? null : 2064 mCecSettingChangeListeners.get(setting).remove(listener); 2065 if (wrappedListener == null) { 2066 Log.e(TAG, "tried to remove not-registered listener"); 2067 return; 2068 } 2069 try { 2070 mService.removeCecSettingChangeListener(setting, wrappedListener); 2071 } catch (RemoteException e) { 2072 throw e.rethrowFromSystemServer(); 2073 } 2074 } 2075 2076 private IHdmiCecSettingChangeListener getCecSettingChangeListenerWrapper( 2077 Executor executor, final CecSettingChangeListener listener) { 2078 return new IHdmiCecSettingChangeListener.Stub() { 2079 @Override 2080 public void onChange(String setting) { 2081 final long token = Binder.clearCallingIdentity(); 2082 try { 2083 executor.execute(() -> listener.onChange(setting)); 2084 } finally { 2085 Binder.restoreCallingIdentity(token); 2086 } 2087 } 2088 }; 2089 } 2090 2091 /** 2092 * Get a set of user-modifiable HDMI control settings. 2093 * This applies to CEC settings and eARC settings. 2094 * 2095 * @return a set of user-modifiable settings. 2096 * @throws RuntimeException when the HdmiControlService is not available. 2097 */ 2098 // TODO(b/240379115): rename this API to represent that this applies to all HDMI control 2099 // settings and not just CEC settings. 2100 @NonNull 2101 @SettingName 2102 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2103 public List<String> getUserCecSettings() { 2104 if (mService == null) { 2105 Log.e(TAG, "getUserCecSettings: HdmiControlService is not available"); 2106 throw new RuntimeException("HdmiControlService is not available"); 2107 } 2108 try { 2109 return mService.getUserCecSettings(); 2110 } catch (RemoteException e) { 2111 throw e.rethrowFromSystemServer(); 2112 } 2113 } 2114 2115 /** 2116 * Get a set of allowed values for an HDMI control setting (string value-type). 2117 * This applies to CEC settings and eARC settings. 2118 * 2119 * 2120 * @param name name of the setting 2121 * @return a set of allowed values for a settings. {@code null} on failure. 2122 * @throws IllegalArgumentException when setting {@code name} does not exist. 2123 * @throws IllegalArgumentException when setting {@code name} value type is invalid. 2124 * @throws RuntimeException when the HdmiControlService is not available. 2125 */ 2126 // TODO(b/240379115): rename this API to represent that this applies to all HDMI control 2127 // settings and not just CEC settings. 2128 @NonNull 2129 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2130 public List<String> getAllowedCecSettingStringValues(@NonNull @SettingName String name) { 2131 if (mService == null) { 2132 Log.e(TAG, "getAllowedCecSettingStringValues: HdmiControlService is not available"); 2133 throw new RuntimeException("HdmiControlService is not available"); 2134 } 2135 try { 2136 return mService.getAllowedCecSettingStringValues(name); 2137 } catch (RemoteException e) { 2138 throw e.rethrowFromSystemServer(); 2139 } 2140 } 2141 2142 /** 2143 * Get a set of allowed values for an HDMI control setting (int value-type). 2144 * This applies to CEC settings and eARC settings. 2145 * 2146 * @param name name of the setting 2147 * @return a set of allowed values for a settings. {@code null} on failure. 2148 * @throws IllegalArgumentException when setting {@code name} does not exist. 2149 * @throws IllegalArgumentException when setting {@code name} value type is invalid. 2150 * @throws RuntimeException when the HdmiControlService is not available. 2151 */ 2152 // TODO(b/240379115): rename this API to represent that this applies to all HDMI control 2153 // settings and not just CEC settings. 2154 @NonNull 2155 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2156 public List<Integer> getAllowedCecSettingIntValues(@NonNull @SettingName String name) { 2157 if (mService == null) { 2158 Log.e(TAG, "getAllowedCecSettingIntValues: HdmiControlService is not available"); 2159 throw new RuntimeException("HdmiControlService is not available"); 2160 } 2161 try { 2162 int[] allowedValues = mService.getAllowedCecSettingIntValues(name); 2163 return Arrays.stream(allowedValues).boxed().collect(Collectors.toList()); 2164 } catch (RemoteException e) { 2165 throw e.rethrowFromSystemServer(); 2166 } 2167 } 2168 2169 /** 2170 * Set the global status of HDMI CEC. 2171 * 2172 * <p>This allows to enable/disable HDMI CEC on the device. 2173 */ 2174 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2175 public void setHdmiCecEnabled(@NonNull @HdmiCecControl int value) { 2176 if (mService == null) { 2177 Log.e(TAG, "setHdmiCecEnabled: HdmiControlService is not available"); 2178 throw new RuntimeException("HdmiControlService is not available"); 2179 } 2180 try { 2181 mService.setCecSettingIntValue(CEC_SETTING_NAME_HDMI_CEC_ENABLED, value); 2182 } catch (RemoteException e) { 2183 throw e.rethrowFromSystemServer(); 2184 } 2185 } 2186 2187 /** 2188 * Get the current global status of HDMI CEC. 2189 * 2190 * <p>Reflects whether HDMI CEC is currently enabled on the device. 2191 */ 2192 @NonNull 2193 @HdmiCecControl 2194 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2195 public int getHdmiCecEnabled() { 2196 if (mService == null) { 2197 Log.e(TAG, "getHdmiCecEnabled: HdmiControlService is not available"); 2198 throw new RuntimeException("HdmiControlService is not available"); 2199 } 2200 try { 2201 return mService.getCecSettingIntValue(CEC_SETTING_NAME_HDMI_CEC_ENABLED); 2202 } catch (RemoteException e) { 2203 throw e.rethrowFromSystemServer(); 2204 } 2205 } 2206 2207 /** 2208 * Add change listener for global status of HDMI CEC. 2209 * 2210 * <p>To stop getting the notification, 2211 * use {@link #removeHdmiCecEnabledChangeListener(CecSettingChangeListener)}. 2212 * 2213 * Note that each invocation of the callback will be executed on an arbitrary 2214 * Binder thread. This means that all callback implementations must be 2215 * thread safe. To specify the execution thread, use 2216 * {@link addHdmiCecEnabledChangeListener(Executor, CecSettingChangeListener)}. 2217 */ 2218 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2219 public void addHdmiCecEnabledChangeListener(@NonNull CecSettingChangeListener listener) { 2220 addHdmiCecEnabledChangeListener(ConcurrentUtils.DIRECT_EXECUTOR, listener); 2221 } 2222 2223 /** 2224 * Add change listener for global status of HDMI CEC. 2225 * 2226 * <p>To stop getting the notification, 2227 * use {@link #removeHdmiCecEnabledChangeListener(CecSettingChangeListener)}. 2228 */ 2229 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2230 public void addHdmiCecEnabledChangeListener( 2231 @NonNull @CallbackExecutor Executor executor, 2232 @NonNull CecSettingChangeListener listener) { 2233 addCecSettingChangeListener(CEC_SETTING_NAME_HDMI_CEC_ENABLED, executor, listener); 2234 } 2235 2236 /** 2237 * Remove change listener for global status of HDMI CEC. 2238 */ 2239 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2240 public void removeHdmiCecEnabledChangeListener( 2241 @NonNull CecSettingChangeListener listener) { 2242 removeCecSettingChangeListener(CEC_SETTING_NAME_HDMI_CEC_ENABLED, listener); 2243 } 2244 2245 /** 2246 * Set the version of the HDMI CEC specification currently used. 2247 * 2248 * <p>Allows to select either CEC 1.4b or 2.0 to be used by the device. 2249 * 2250 * @see HdmiControlManager#CEC_SETTING_NAME_HDMI_CEC_VERSION 2251 */ 2252 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2253 public void setHdmiCecVersion(@NonNull @HdmiCecVersion int value) { 2254 if (mService == null) { 2255 Log.e(TAG, "setHdmiCecVersion: HdmiControlService is not available"); 2256 throw new RuntimeException("HdmiControlService is not available"); 2257 } 2258 try { 2259 mService.setCecSettingIntValue(CEC_SETTING_NAME_HDMI_CEC_VERSION, value); 2260 } catch (RemoteException e) { 2261 throw e.rethrowFromSystemServer(); 2262 } 2263 } 2264 2265 /** 2266 * Get the version of the HDMI CEC specification currently used. 2267 * 2268 * <p>Reflects which CEC version 1.4b or 2.0 is currently used by the device. 2269 * 2270 * @see HdmiControlManager#CEC_SETTING_NAME_HDMI_CEC_VERSION 2271 */ 2272 @NonNull 2273 @HdmiCecVersion 2274 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2275 public int getHdmiCecVersion() { 2276 if (mService == null) { 2277 Log.e(TAG, "getHdmiCecVersion: HdmiControlService is not available"); 2278 throw new RuntimeException("HdmiControlService is not available"); 2279 } 2280 try { 2281 return mService.getCecSettingIntValue(CEC_SETTING_NAME_HDMI_CEC_VERSION); 2282 } catch (RemoteException e) { 2283 throw e.rethrowFromSystemServer(); 2284 } 2285 } 2286 2287 /** 2288 * Set the status of Routing Control feature. 2289 * 2290 * <p>This allows to enable/disable Routing Control on the device. 2291 * If enabled, the switch device will route to the correct input source on 2292 * receiving Routing Control related messages. If disabled, you can only 2293 * switch the input via controls on this device. 2294 * 2295 * @see HdmiControlManager#CEC_SETTING_NAME_ROUTING_CONTROL 2296 */ 2297 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2298 public void setRoutingControl(@NonNull @RoutingControl int value) { 2299 if (mService == null) { 2300 Log.e(TAG, "setRoutingControl: HdmiControlService is not available"); 2301 throw new RuntimeException("HdmiControlService is not available"); 2302 } 2303 try { 2304 mService.setCecSettingIntValue(CEC_SETTING_NAME_ROUTING_CONTROL, value); 2305 } catch (RemoteException e) { 2306 throw e.rethrowFromSystemServer(); 2307 } 2308 } 2309 2310 /** 2311 * Get the current status of Routing Control feature. 2312 * 2313 * <p>Reflects whether Routing Control is currently enabled on the device. 2314 * If enabled, the switch device will route to the correct input source on 2315 * receiving Routing Control related messages. If disabled, you can only 2316 * switch the input via controls on this device. 2317 * 2318 * @see HdmiControlManager#CEC_SETTING_NAME_ROUTING_CONTROL 2319 */ 2320 @NonNull 2321 @RoutingControl 2322 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2323 public int getRoutingControl() { 2324 if (mService == null) { 2325 Log.e(TAG, "getRoutingControl: HdmiControlService is not available"); 2326 throw new RuntimeException("HdmiControlService is not available"); 2327 } 2328 try { 2329 return mService.getCecSettingIntValue(CEC_SETTING_NAME_ROUTING_CONTROL); 2330 } catch (RemoteException e) { 2331 throw e.rethrowFromSystemServer(); 2332 } 2333 } 2334 2335 /** 2336 * Set the status of Soundbar mode feature. 2337 * 2338 * <p>This allows to enable/disable Soundbar mode on the playback device. 2339 * The setting's effect will be available on devices where the hardware supports this feature. 2340 * If enabled, an audio system local device will be allocated and try to establish an ARC 2341 * connection with the TV. If disabled, the ARC connection will be terminated and the audio 2342 * system local device will be removed from the network. 2343 * 2344 * @see HdmiControlManager#CEC_SETTING_NAME_SOUNDBAR_MODE 2345 */ 2346 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2347 public void setSoundbarMode(@SoundbarMode int value) { 2348 if (mService == null) { 2349 Log.e(TAG, "setSoundbarMode: HdmiControlService is not available"); 2350 throw new RuntimeException("HdmiControlService is not available"); 2351 } 2352 try { 2353 mService.setCecSettingIntValue(CEC_SETTING_NAME_SOUNDBAR_MODE, value); 2354 } catch (RemoteException e) { 2355 throw e.rethrowFromSystemServer(); 2356 } 2357 } 2358 2359 /** 2360 * Get the current status of Soundbar mode feature. 2361 * 2362 * <p>Reflects whether Soundbar mode is currently enabled on the playback device. 2363 * If enabled, an audio system local device will be allocated and try to establish an ARC 2364 * connection with the TV. If disabled, the ARC connection will be terminated and the audio 2365 * system local device will be removed from the network. 2366 * 2367 * @see HdmiControlManager#CEC_SETTING_NAME_SOUNDBAR_MODE 2368 */ 2369 @SoundbarMode 2370 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2371 public int getSoundbarMode() { 2372 if (mService == null) { 2373 Log.e(TAG, "getSoundbarMode: HdmiControlService is not available"); 2374 throw new RuntimeException("HdmiControlService is not available"); 2375 } 2376 try { 2377 return mService.getCecSettingIntValue(CEC_SETTING_NAME_SOUNDBAR_MODE); 2378 } catch (RemoteException e) { 2379 throw e.rethrowFromSystemServer(); 2380 } 2381 } 2382 2383 /** 2384 * Set the status of Power Control. 2385 * 2386 * <p>Specifies to which devices Power Control messages should be sent: 2387 * only to the TV, broadcast to all devices, no power control messages. 2388 * 2389 * @see HdmiControlManager#CEC_SETTING_NAME_POWER_CONTROL_MODE 2390 */ 2391 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2392 public void setPowerControlMode(@NonNull @PowerControlMode String value) { 2393 if (mService == null) { 2394 Log.e(TAG, "setPowerControlMode: HdmiControlService is not available"); 2395 throw new RuntimeException("HdmiControlService is not available"); 2396 } 2397 try { 2398 mService.setCecSettingStringValue(CEC_SETTING_NAME_POWER_CONTROL_MODE, value); 2399 } catch (RemoteException e) { 2400 throw e.rethrowFromSystemServer(); 2401 } 2402 } 2403 2404 /** 2405 * Get the status of Power Control. 2406 * 2407 * <p>Reflects to which devices Power Control messages should be sent: 2408 * only to the TV, broadcast to all devices, no power control messages. 2409 * 2410 * @see HdmiControlManager#CEC_SETTING_NAME_POWER_CONTROL_MODE 2411 */ 2412 @NonNull 2413 @PowerControlMode 2414 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2415 public String getPowerControlMode() { 2416 if (mService == null) { 2417 Log.e(TAG, "getPowerControlMode: HdmiControlService is not available"); 2418 throw new RuntimeException("HdmiControlService is not available"); 2419 } 2420 try { 2421 return mService.getCecSettingStringValue(CEC_SETTING_NAME_POWER_CONTROL_MODE); 2422 } catch (RemoteException e) { 2423 throw e.rethrowFromSystemServer(); 2424 } 2425 } 2426 2427 /** 2428 * Set the current power state behaviour when Active Source is lost. 2429 * 2430 * <p>Sets the action taken: do nothing or go to sleep immediately. 2431 * 2432 * @see HdmiControlManager#CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST 2433 */ 2434 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2435 public void setPowerStateChangeOnActiveSourceLost( 2436 @NonNull @ActiveSourceLostBehavior String value) { 2437 if (mService == null) { 2438 Log.e(TAG, 2439 "setPowerStateChangeOnActiveSourceLost: HdmiControlService is not available"); 2440 throw new RuntimeException("HdmiControlService is not available"); 2441 } 2442 try { 2443 mService.setCecSettingStringValue( 2444 CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, value); 2445 } catch (RemoteException e) { 2446 throw e.rethrowFromSystemServer(); 2447 } 2448 } 2449 2450 /** 2451 * Get the current power state behaviour when Active Source is lost. 2452 * 2453 * <p>Reflects the action taken: do nothing or go to sleep immediately. 2454 * 2455 * @see HdmiControlManager#CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST 2456 */ 2457 @NonNull 2458 @ActiveSourceLostBehavior 2459 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2460 public String getPowerStateChangeOnActiveSourceLost() { 2461 if (mService == null) { 2462 Log.e(TAG, 2463 "getPowerStateChangeOnActiveSourceLost: HdmiControlService is not available"); 2464 throw new RuntimeException("HdmiControlService is not available"); 2465 } 2466 try { 2467 return mService.getCecSettingStringValue( 2468 CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST); 2469 } catch (RemoteException e) { 2470 throw e.rethrowFromSystemServer(); 2471 } 2472 } 2473 2474 /** 2475 * Set the current status of System Audio Control. 2476 * 2477 * <p>Sets whether HDMI System Audio Control feature is enabled. If enabled, 2478 * TV or Audio System will try to turn on the System Audio Mode if there's a 2479 * connected CEC-enabled AV Receiver. Then an audio stream will be played on 2480 * the AVR instead of TV speaker or Audio System speakers. If disabled, the 2481 * System Audio Mode will never be activated. 2482 * 2483 * @see HdmiControlManager#CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL 2484 */ 2485 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2486 public void setSystemAudioControl(@NonNull @SystemAudioControl int value) { 2487 if (mService == null) { 2488 Log.e(TAG, "setSystemAudioControl: HdmiControlService is not available"); 2489 throw new RuntimeException("HdmiControlService is not available"); 2490 } 2491 try { 2492 mService.setCecSettingIntValue(CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL, value); 2493 } catch (RemoteException e) { 2494 throw e.rethrowFromSystemServer(); 2495 } 2496 } 2497 2498 /** 2499 * Get the current status of System Audio Control. 2500 * 2501 * <p>Reflects whether HDMI System Audio Control feature is enabled. If enabled, 2502 * TV or Audio System will try to turn on the System Audio Mode if there's a 2503 * connected CEC-enabled AV Receiver. Then an audio stream will be played on 2504 * the AVR instead of TV speaker or Audio System speakers. If disabled, the 2505 * System Audio Mode will never be activated. 2506 * 2507 * @see HdmiControlManager#CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL 2508 */ 2509 @NonNull 2510 @SystemAudioControl 2511 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2512 public int getSystemAudioControl() { 2513 if (mService == null) { 2514 Log.e(TAG, "getSystemAudioControl: HdmiControlService is not available"); 2515 throw new RuntimeException("HdmiControlService is not available"); 2516 } 2517 try { 2518 return mService.getCecSettingIntValue(CEC_SETTING_NAME_SYSTEM_AUDIO_CONTROL); 2519 } catch (RemoteException e) { 2520 throw e.rethrowFromSystemServer(); 2521 } 2522 } 2523 2524 /** 2525 * Set the current status of System Audio Mode muting. 2526 * 2527 * <p>Sets whether the device should be muted when System Audio Mode is turned off. 2528 * 2529 * @see HdmiControlManager#CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING 2530 */ 2531 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2532 public void setSystemAudioModeMuting(@NonNull @SystemAudioModeMuting int value) { 2533 if (mService == null) { 2534 Log.e(TAG, "setSystemAudioModeMuting: HdmiControlService is not available"); 2535 throw new RuntimeException("HdmiControlService is not available"); 2536 } 2537 try { 2538 mService.setCecSettingIntValue(CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, value); 2539 } catch (RemoteException e) { 2540 throw e.rethrowFromSystemServer(); 2541 } 2542 } 2543 2544 /** 2545 * Get the current status of System Audio Mode muting. 2546 * 2547 * <p>Reflects whether the device should be muted when System Audio Mode is turned off. 2548 * 2549 * @see HdmiControlManager#CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING 2550 */ 2551 @NonNull 2552 @SystemAudioModeMuting 2553 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2554 public int getSystemAudioModeMuting() { 2555 if (mService == null) { 2556 Log.e(TAG, "getSystemAudioModeMuting: HdmiControlService is not available"); 2557 throw new RuntimeException("HdmiControlService is not available"); 2558 } 2559 try { 2560 return mService.getCecSettingIntValue(CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING); 2561 } catch (RemoteException e) { 2562 throw e.rethrowFromSystemServer(); 2563 } 2564 } 2565 2566 /** 2567 * Set the current status of TV Wake on One Touch Play. 2568 * 2569 * <p>Sets whether the TV should wake up upon reception of <Text View On> 2570 * or <Image View On>. 2571 * 2572 * @see HdmiControlManager#CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY 2573 */ 2574 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2575 public void setTvWakeOnOneTouchPlay(@NonNull @TvWakeOnOneTouchPlay int value) { 2576 if (mService == null) { 2577 Log.e(TAG, "setTvWakeOnOneTouchPlay: HdmiControlService is not available"); 2578 throw new RuntimeException("HdmiControlService is not available"); 2579 } 2580 try { 2581 mService.setCecSettingIntValue(CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY, value); 2582 } catch (RemoteException e) { 2583 throw e.rethrowFromSystemServer(); 2584 } 2585 } 2586 2587 /** 2588 * Get the current status of TV Wake on One Touch Play. 2589 * 2590 * <p>Reflects whether the TV should wake up upon reception of <Text View On> 2591 * or <Image View On>. 2592 * 2593 * @see HdmiControlManager#CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY 2594 */ 2595 @NonNull 2596 @TvWakeOnOneTouchPlay 2597 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2598 public int getTvWakeOnOneTouchPlay() { 2599 if (mService == null) { 2600 Log.e(TAG, "getTvWakeOnOneTouchPlay: HdmiControlService is not available"); 2601 throw new RuntimeException("HdmiControlService is not available"); 2602 } 2603 try { 2604 return mService.getCecSettingIntValue(CEC_SETTING_NAME_TV_WAKE_ON_ONE_TOUCH_PLAY); 2605 } catch (RemoteException e) { 2606 throw e.rethrowFromSystemServer(); 2607 } 2608 } 2609 2610 /** 2611 * Set the current status of TV send <Standby> on Sleep. 2612 * 2613 * <p>Sets whether the device will also turn off other CEC devices 2614 * when it goes to standby mode. 2615 * 2616 * @see HdmiControlManager#CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP 2617 */ 2618 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2619 public void setTvSendStandbyOnSleep(@NonNull @TvSendStandbyOnSleep int value) { 2620 if (mService == null) { 2621 Log.e(TAG, "setTvSendStandbyOnSleep: HdmiControlService is not available"); 2622 throw new RuntimeException("HdmiControlService is not available"); 2623 } 2624 try { 2625 mService.setCecSettingIntValue(CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP, value); 2626 } catch (RemoteException e) { 2627 throw e.rethrowFromSystemServer(); 2628 } 2629 } 2630 2631 /** 2632 * Get the current status of TV send <Standby> on Sleep. 2633 * 2634 * <p>Reflects whether the device will also turn off other CEC devices 2635 * when it goes to standby mode. 2636 * 2637 * @see HdmiControlManager#CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP 2638 */ 2639 @NonNull 2640 @TvSendStandbyOnSleep 2641 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2642 public int getTvSendStandbyOnSleep() { 2643 if (mService == null) { 2644 Log.e(TAG, "getTvSendStandbyOnSleep: HdmiControlService is not available"); 2645 throw new RuntimeException("HdmiControlService is not available"); 2646 } 2647 try { 2648 return mService.getCecSettingIntValue(CEC_SETTING_NAME_TV_SEND_STANDBY_ON_SLEEP); 2649 } catch (RemoteException e) { 2650 throw e.rethrowFromSystemServer(); 2651 } 2652 } 2653 2654 /** 2655 * Set presence of one Short Audio Descriptor (SAD) in the query. 2656 * 2657 * <p>Allows the caller to specify whether the SAD for a specific audio codec should be 2658 * present in the <Request Short Audio Descriptor> query. Each <Request Short Audio 2659 * Descriptor> message can carry at most 4 SADs at a time. This method allows the caller to 2660 * limit the amount of SADs queried and therefore limit the amount of CEC messages on the bus. 2661 * 2662 * <p>When an ARC connection is established, the TV sends a 2663 * <Request Short Audio Descriptor> query to the Audio System that it's connected to. If 2664 * an SAD is queried and the Audio System reports that it supports that SAD, the TV can send 2665 * audio in that format to be output on the Audio System via ARC. 2666 * If a codec is not queried, the TV doesn't know if the connected Audio System supports this 2667 * SAD and doesn't send audio in that format to the Audio System. 2668 * 2669 * @param setting SAD to set. 2670 * @param value Presence to set the SAD to. 2671 */ 2672 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2673 public void setSadPresenceInQuery(@NonNull @CecSettingSad String setting, 2674 @SadPresenceInQuery int value) { 2675 if (mService == null) { 2676 Log.e(TAG, "setSadPresenceInQuery: HdmiControlService is not available"); 2677 throw new RuntimeException("HdmiControlService is not available"); 2678 } 2679 try { 2680 mService.setCecSettingIntValue(setting, value); 2681 } catch (RemoteException e) { 2682 throw e.rethrowFromSystemServer(); 2683 } 2684 } 2685 2686 /** 2687 * Set presence of multiple Short Audio Descriptors (SADs) in the query. 2688 * 2689 * <p>Allows the caller to specify whether the SADs for specific audio codecs should be present 2690 * in the <Request Short Audio Descriptor> query. For audio codecs that are not specified, 2691 * the SAD's presence remains at its previous value. Each <Request Short Audio Descriptor> 2692 * message can carry at most 4 SADs at a time. This method allows the caller to limit the amount 2693 * of SADs queried and therefore limit the amount of CEC messages on the bus. 2694 * 2695 * <p>When an ARC connection is established, the TV sends a 2696 * <Request Short Audio Descriptor> query to the Audio System that it's connected to. If 2697 * an SAD is queried and the Audio System reports that it supports that SAD, the TV can send 2698 * audio in that format to be output on the Audio System via ARC. 2699 * If a codec is not queried, the TV doesn't know if the connected Audio System supports this 2700 * SAD and doesn't send audio in that format to the Audio System. 2701 * 2702 * 2703 * @param settings SADs to set. 2704 * @param value Presence to set all specified SADs to. 2705 */ 2706 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2707 public void setSadsPresenceInQuery(@NonNull @CecSettingSad List<String> settings, 2708 @SadPresenceInQuery int value) { 2709 if (mService == null) { 2710 Log.e(TAG, "setSadsPresenceInQuery: HdmiControlService is not available"); 2711 throw new RuntimeException("HdmiControlService is not available"); 2712 } 2713 try { 2714 for (String sad : settings) { 2715 mService.setCecSettingIntValue(sad, value); 2716 } 2717 } catch (RemoteException e) { 2718 throw e.rethrowFromSystemServer(); 2719 } 2720 } 2721 2722 /** 2723 * Get presence of one Short Audio Descriptor (SAD) in the query. 2724 * 2725 * <p>Reflects whether the SAD for a specific audio codec should be present in the 2726 * <Request Short Audio Descriptor> query. 2727 * 2728 * <p>When an ARC connection is established, the TV sends a 2729 * <Request Short Audio Descriptor> query to the Audio System that it's connected to. If 2730 * an SAD is queried and the Audio System reports that it supports that SAD, the TV can send 2731 * audio in that format to be output on the Audio System via ARC. 2732 * If a codec is not queried, the TV doesn't know if the connected Audio System supports this 2733 * SAD and doesn't send audio in that format to the Audio System. 2734 * 2735 * @param setting SAD to get. 2736 * @return Current presence of the specified SAD. 2737 */ 2738 @SadPresenceInQuery 2739 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2740 public int getSadPresenceInQuery(@NonNull @CecSettingSad String setting) { 2741 if (mService == null) { 2742 Log.e(TAG, "getSadPresenceInQuery: HdmiControlService is not available"); 2743 throw new RuntimeException("HdmiControlService is not available"); 2744 } 2745 try { 2746 return mService.getCecSettingIntValue(setting); 2747 } catch (RemoteException e) { 2748 throw e.rethrowFromSystemServer(); 2749 } 2750 } 2751 2752 /** 2753 * Set the global status of eARC. 2754 * 2755 * <p>This allows to enable/disable the eARC feature on the device. If the feature is enabled 2756 * and the hardware supports eARC as well, the device can attempt to establish an eARC 2757 * connection. 2758 */ 2759 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2760 public void setEarcEnabled(@NonNull @EarcFeature int value) { 2761 if (mService == null) { 2762 Log.e(TAG, "setEarcEnabled: HdmiControlService is not available"); 2763 throw new RuntimeException("HdmiControlService is not available"); 2764 } 2765 try { 2766 mService.setCecSettingIntValue(SETTING_NAME_EARC_ENABLED, value); 2767 } catch (RemoteException e) { 2768 throw e.rethrowFromSystemServer(); 2769 } 2770 } 2771 2772 /** 2773 * Get the current global status of eARC. 2774 * 2775 * <p>Reflects whether the eARC feature is currently enabled on the device. 2776 */ 2777 @NonNull 2778 @EarcFeature 2779 @RequiresPermission(android.Manifest.permission.HDMI_CEC) 2780 public int getEarcEnabled() { 2781 if (mService == null) { 2782 Log.e(TAG, "getEarcEnabled: HdmiControlService is not available"); 2783 throw new RuntimeException("HdmiControlService is not available"); 2784 } 2785 try { 2786 return mService.getCecSettingIntValue(SETTING_NAME_EARC_ENABLED); 2787 } catch (RemoteException e) { 2788 throw e.rethrowFromSystemServer(); 2789 } 2790 } 2791 } 2792