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