191120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim/*
291120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * Copyright (C) 2014 The Android Open Source Project
391120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim *
491120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * Licensed under the Apache License, Version 2.0 (the "License");
591120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * you may not use this file except in compliance with the License.
691120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * You may obtain a copy of the License at
791120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim *
891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim *      http://www.apache.org/licenses/LICENSE-2.0
991120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim *
1091120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * Unless required by applicable law or agreed to in writing, software
1191120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * distributed under the License is distributed on an "AS IS" BASIS,
1291120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1391120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * See the License for the specific language governing permissions and
1491120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * limitations under the License.
1591120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim */
1691120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim
1791120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kimpackage android.hardware.hdmi;
1891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim
1991120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kimimport android.annotation.Nullable;
20c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kimimport android.annotation.SdkConstant;
21c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kimimport android.annotation.SdkConstant.SdkConstantType;
2266d1eb285b129836d1b3c392ed609283c0dbf830Jinsuk Kimimport android.annotation.SystemApi;
2378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kimimport android.os.RemoteException;
242b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heoimport android.util.ArrayMap;
252b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heoimport android.util.Log;
2678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim
2791120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim/**
2891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * The {@link HdmiControlManager} class is used to send HDMI control messages
2991120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * to attached CEC devices.
3091120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim *
3191120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * <p>Provides various HDMI client instances that represent HDMI-CEC logical devices
3291120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * hosted in the system. {@link #getTvClient()}, for instance will return an
3391120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * {@link HdmiTvClient} object if the system is configured to host one. Android system
3491120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * can host more than one logical CEC devices. If multiple types are configured they
3591120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * all work as if they were independent logical devices running in the system.
3666d1eb285b129836d1b3c392ed609283c0dbf830Jinsuk Kim *
3766d1eb285b129836d1b3c392ed609283c0dbf830Jinsuk Kim * @hide
3891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim */
3966d1eb285b129836d1b3c392ed609283c0dbf830Jinsuk Kim@SystemApi
4091120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kimpublic final class HdmiControlManager {
412b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo    private static final String TAG = "HdmiControlManager";
422b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo
4391120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim    @Nullable private final IHdmiControlService mService;
4491120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim
45c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim    /**
46c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim     * Broadcast Action: Display OSD message.
47c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim     * <p>Send when the service has a message to display on screen for events
48c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim     * that need user's attention such as ARC status change.
49e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang     * <p>Always contains the extra fields {@link #EXTRA_MESSAGE_ID}.
50c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim     * <p>Requires {@link android.Manifest.permission#HDMI_CEC} to receive.
51c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim     */
52c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
53c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim    public static final String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE";
54c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim
55339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang    // --- Messages for ACTION_OSD_MESSAGE ---
56339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang    /**
57339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang     * Message that ARC enabled device is connected to invalid port (non-ARC port).
58339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang     */
59339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang    public static final int OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT = 1;
60339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang
61c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim    /**
622e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang     * Message used by TV to receive volume status from Audio Receiver. It should check volume value
632b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo     * that is retrieved from extra value with the key {@link #EXTRA_MESSAGE_EXTRA_PARAM1}. If the
642e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang     * value is in range of [0,100], it is current volume of Audio Receiver. And there is another
652e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang     * value, {@link #AVR_VOLUME_MUTED}, which is used to inform volume mute.
662e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang     */
672e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang    public static final int OSD_MESSAGE_AVR_VOLUME_CHANGED = 2;
682e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang
692e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang    /**
70c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim     * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the ID of
71c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim     * the message to display on screen.
72c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim     */
73c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim    public static final String EXTRA_MESSAGE_ID = "android.hardware.hdmi.extra.MESSAGE_ID";
742e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang    /**
752e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang     * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the extra value
762e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang     * of the message.
772e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang     */
782b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo    public static final String EXTRA_MESSAGE_EXTRA_PARAM1 =
792e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang            "android.hardware.hdmi.extra.MESSAGE_EXTRA_PARAM1";
802e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang
812e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang    /**
822e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang     * Volume value for mute state.
832e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang     */
842e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang    public static final int AVR_VOLUME_MUTED = 101;
85c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim
86c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim    public static final int POWER_STATUS_UNKNOWN = -1;
87c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim    public static final int POWER_STATUS_ON = 0;
88c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim    public static final int POWER_STATUS_STANDBY = 1;
89c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim    public static final int POWER_STATUS_TRANSIENT_TO_ON = 2;
90c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim    public static final int POWER_STATUS_TRANSIENT_TO_STANDBY = 3;
91c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim
92c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim    public static final int RESULT_SUCCESS = 0;
93c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim    public static final int RESULT_TIMEOUT = 1;
94c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim    public static final int RESULT_SOURCE_NOT_AVAILABLE = 2;
95c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim    public static final int RESULT_TARGET_NOT_AVAILABLE = 3;
96cb802870f7f855c429556643fd67179a7b5dc747Jinsuk Kim
97cb802870f7f855c429556643fd67179a7b5dc747Jinsuk Kim    @Deprecated public static final int RESULT_ALREADY_IN_PROGRESS = 4;
98c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim    public static final int RESULT_EXCEPTION = 5;
99c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim    public static final int RESULT_INCORRECT_MODE = 6;
100b38cd68b240d99e8c8ae6ff1802a574696b420cdJinsuk Kim    public static final int RESULT_COMMUNICATION_FAILED = 7;
101c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim
10261daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang    public static final int DEVICE_EVENT_ADD_DEVICE = 1;
10361daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang    public static final int DEVICE_EVENT_REMOVE_DEVICE = 2;
10461daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang    public static final int DEVICE_EVENT_UPDATE_DEVICE = 3;
10561daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang
10612e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    // --- One Touch Recording success result
107b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** Recording currently selected source. Indicates the status of a recording. */
10812e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_RECORDING_CURRENTLY_SELECTED_SOURCE = 0x01;
109b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** Recording Digital Service. Indicates the status of a recording. */
11012e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE = 0x02;
111b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** Recording Analogue Service. Indicates the status of a recording. */
11212e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_RECORDING_ANALOGUE_SERVICE = 0x03;
113b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** Recording External input. Indicates the status of a recording. */
11412e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT = 0x04;
11512e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang
11612e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    // --- One Touch Record failure result
117b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – unable to record Digital Service. No suitable tuner. */
11812e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_UNABLE_DIGITAL_SERVICE = 0x05;
119b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – unable to record Analogue Service. No suitable tuner. */
12012e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_UNABLE_ANALOGUE_SERVICE = 0x06;
121b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /**
122b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang     * No recording – unable to select required service. as suitable tuner, but the requested
123b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang     * parameters are invalid or out of range for that tuner.
124b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang     */
12512e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_UNABLE_SELECTED_SERVICE = 0x07;
126b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – invalid External plug number */
12712e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PLUG_NUMBER = 0x09;
128b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – invalid External Physical Address */
12912e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 0x0A;
130b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – CA system not supported */
13112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_UNSUPPORTED_CA = 0x0B;
132b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No Recording – No or Insufficient CA Entitlements” */
13312e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_NO_OR_INSUFFICIENT_CA_ENTITLEMENTS = 0x0C;
134b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – Not allowed to copy source. Source is “copy never”. */
13512e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_DISALLOW_TO_COPY = 0x0D;
136b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – No further copies allowed */
13712e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_DISALLOW_TO_FUTHER_COPIES = 0x0E;
138b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – No media */
13912e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_NO_MEDIA = 0x10;
140b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – playing */
14112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_PLAYING = 0x11;
142b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – already recording */
14312e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_ALREADY_RECORDING = 0x12;
144b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – media protected */
14512e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_MEDIA_PROTECTED = 0x13;
146b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – no source signal */
14712e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_NO_SOURCE_SIGNAL = 0x14;
148b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – media problem */
14912e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_MEDIA_PROBLEM = 0x15;
150b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – not enough space available */
15112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_NOT_ENOUGH_SPACE = 0x16;
152b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – Parental Lock On */
15312e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_PARENT_LOCK_ON = 0x17;
154b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** Recording terminated normally */
15512e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_RECORDING_TERMINATED_NORMALLY = 0x1A;
156b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** Recording has already terminated */
15712e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_RECORDING_ALREADY_TERMINATED = 0x1B;
158b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording – other reason */
15912e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_OTHER_REASON = 0x1F;
160b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    // From here extra message for recording that is not mentioned in CEC spec
161b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording. Previous recording request in progress. */
16212e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_PREVIOUS_RECORDING_IN_PROGRESS = 0x30;
163b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** No recording. Please check recorder and connection. */
16412e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION = 0x31;
165b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** Cannot record currently displayed source. */
16612e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN = 0x32;
16712e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    /** CEC is disabled. */
16812e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    public static final int ONE_TOUCH_RECORD_CEC_DISABLED = 0x33;
169b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang
17012e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    // --- Types for timer recording
171b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** Timer recording type for digital service source. */
172b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    public static final int TIMER_RECORDING_TYPE_DIGITAL = 1;
173b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** Timer recording type for analogue service source. */
174b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    public static final int TIMER_RECORDING_TYPE_ANALOGUE = 2;
175b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    /** Timer recording type for external source. */
176b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    public static final int TIMER_RECORDING_TYPE_EXTERNAL = 3;
177b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang
178e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    // --- Timer Status Data
179e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Media Info] - Media present and not protected. */
180e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_MEDIA_INFO_PRESENT_NOT_PROTECTED = 0x0;
181e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Media Info] - Media present, but protected. */
182e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_MEDIA_INFO_PRESENT_PROTECTED = 0x1;
183e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Media Info] - Media not present. */
184e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_MEDIA_INFO_NOT_PRESENT = 0x2;
185e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang
186e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Programmed Info] - Enough space available for recording. */
187e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_PROGRAMMED_INFO_ENOUGH_SPACE = 0x8;
188e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Programmed Info] - Not enough space available for recording. */
189e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_PROGRAMMED_INFO_NOT_ENOUGH_SPACE = 0x9;
190e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Programmed Info] - Might not enough space available for recording. */
191e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_PROGRAMMED_INFO_MIGHT_NOT_ENOUGH_SPACE = 0xB;
192e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Programmed Info] - No media info available. */
193e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_PROGRAMMED_INFO_NO_MEDIA_INFO = 0xA;
194e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang
195e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Not Programmed Error Info] - No free timer available. */
196e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_NOT_PROGRAMMED_NO_FREE_TIME = 0x1;
197e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Not Programmed Error Info] - Date out of range. */
198e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_NOT_PROGRAMMED_DATE_OUT_OF_RANGE = 0x2;
199e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Not Programmed Error Info] - Recording Sequence error. */
200e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_SEQUENCE = 0x3;
201e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Not Programmed Error Info] - Invalid External Plug Number. */
202e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_EXTERNAL_PLUG_NUMBER = 0x4;
203e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Not Programmed Error Info] - Invalid External Physical Address. */
204e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_EXTERNAL_PHYSICAL_NUMBER = 0x5;
205e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Not Programmed Error Info] - CA system not supported. */
206e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_NOT_PROGRAMMED_CA_NOT_SUPPORTED = 0x6;
207e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Not Programmed Error Info] - No or insufficient CA Entitlements. */
208e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_NOT_PROGRAMMED_NO_CA_ENTITLEMENTS = 0x7;
209e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Not Programmed Error Info] - Does not support resolution. */
210e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_NOT_PROGRAMMED_UNSUPPORTED_RESOLUTION = 0x8;
211e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Not Programmed Error Info] - Parental Lock On. */
212e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_NOT_PROGRAMMED_PARENTAL_LOCK_ON= 0x9;
213e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Not Programmed Error Info] - Clock Failure. */
214e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_NOT_PROGRAMMED_CLOCK_FAILURE = 0xA;
215e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** [Timer Status Data/Not Programmed Error Info] - Duplicate: already programmed. */
216e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_STATUS_NOT_PROGRAMMED_DUPLICATED = 0xE;
217e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang
21812e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    // --- Extra result value for timer recording.
219e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** No extra error. */
220e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_RECORDING_RESULT_EXTRA_NO_ERROR = 0x00;
22112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    /** No timer recording - check recorder and connection. */
222e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION = 0x01;
22312e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    /** No timer recording - cannot record selected source. */
224e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE = 0x02;
22512e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    /** CEC is disabled. */
226e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int TIMER_RECORDING_RESULT_EXTRA_CEC_DISABLED = 0x03;
227e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang
228e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    // -- Timer cleared status data code used for result of onClearTimerRecordingResult.
229e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** Timer not cleared – recording. */
230e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_RECORDING = 0x00;
231e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** Timer not cleared – no matching. */
232e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_NO_MATCHING = 0x01;
233e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** Timer not cleared – no info available. */
234e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_NO_INFO_AVAILABLE = 0x02;
235e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** Timer cleared. */
236e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int CLEAR_TIMER_STATUS_TIMER_CLEARED = 0x80;
237e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** Clear timer error - check recorder and connection. */
238e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int CLEAR_TIMER_STATUS_CHECK_RECORDER_CONNECTION = 0xA0;
239e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** Clear timer error - cannot clear timer for selected source. */
240e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE = 0xA1;
241e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    /** Clear timer error - CEC is disabled. */
242e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang    public static final int CLEAR_TIMER_STATUS_CEC_DISABLE = 0xA2;
24312e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang
2440608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo    /** The HdmiControlService is started. */
2450608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo    public static final int CONTROL_STATE_CHANGED_REASON_START = 0;
2460608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo    /** The state of HdmiControlService is changed by changing of settings. */
2470608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo    public static final int CONTROL_STATE_CHANGED_REASON_SETTING = 1;
2480608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo    /** The HdmiControlService is enabled to wake up. */
2490608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo    public static final int CONTROL_STATE_CHANGED_REASON_WAKEUP = 2;
2500608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo    /** The HdmiControlService will be disabled to standby. */
2510608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo    public static final int CONTROL_STATE_CHANGED_REASON_STANDBY = 3;
2520608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo
25378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    // True if we have a logical device of type playback hosted in the system.
25478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    private final boolean mHasPlaybackDevice;
25578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    // True if we have a logical device of type TV hosted in the system.
25678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    private final boolean mHasTvDevice;
25778d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim
25891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim    /**
2592b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo     * {@hide} - hide this constructor because it has a parameter of type IHdmiControlService,
2602b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo     * which is a system private class. The right way to create an instance of this class is
2612b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo     * using the factory Context.getSystemService.
26291120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     */
26391120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim    public HdmiControlManager(IHdmiControlService service) {
26491120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim        mService = service;
26578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        int[] types = null;
26678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        if (mService != null) {
26778d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim            try {
26878d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim                types = mService.getSupportedTypes();
26978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim            } catch (RemoteException e) {
270c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw e.rethrowFromSystemServer();
27178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim            }
27278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        }
27361f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang        mHasTvDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_TV);
27461f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang        mHasPlaybackDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_PLAYBACK);
27578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    }
27678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim
27778d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    private static boolean hasDeviceType(int[] types, int type) {
27878d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        if (types == null) {
27978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim            return false;
28078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        }
28178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        for (int t : types) {
28278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim            if (t == type) {
28378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim                return true;
28478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim            }
28578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        }
28678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        return false;
28791120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim    }
28891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim
28991120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim    /**
2906ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim     * Gets an object that represents an HDMI-CEC logical device of a specified type.
2916ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim     *
2926ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim     * @param type CEC device type
2936ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim     * @return {@link HdmiClient} instance. {@code null} on failure.
29461f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang     * See {@link HdmiDeviceInfo#DEVICE_PLAYBACK}
29561f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang     * See {@link HdmiDeviceInfo#DEVICE_TV}
2966ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim     */
2976ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim    @Nullable
2986ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim    public HdmiClient getClient(int type) {
2996ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim        if (mService == null) {
3006ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim            return null;
3016ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim        }
3026ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim        switch (type) {
30361f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang            case HdmiDeviceInfo.DEVICE_TV:
3046ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim                return mHasTvDevice ? new HdmiTvClient(mService) : null;
30561f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang            case HdmiDeviceInfo.DEVICE_PLAYBACK:
3066ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim                return mHasPlaybackDevice ? new HdmiPlaybackClient(mService) : null;
3076ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim            default:
3086ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim                return null;
3096ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim        }
3106ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim    }
3116ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim
3126ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim    /**
3136ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim     * Gets an object that represents an HDMI-CEC logical device of type playback on the system.
31491120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     *
31591120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     * <p>Used to send HDMI control messages to other devices like TV or audio amplifier through
31691120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     * HDMI bus. It is also possible to communicate with other logical devices hosted in the same
31791120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     * system if the system is configured to host more than one type of HDMI-CEC logical devices.
31891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     *
31991120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     * @return {@link HdmiPlaybackClient} instance. {@code null} on failure.
32091120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     */
32191120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim    @Nullable
32291120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim    public HdmiPlaybackClient getPlaybackClient() {
32361f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang        return (HdmiPlaybackClient) getClient(HdmiDeviceInfo.DEVICE_PLAYBACK);
32491120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim    }
32591120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim
32691120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim    /**
3276ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim     * Gets an object that represents an HDMI-CEC logical device of type TV on the system.
32891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     *
32991120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     * <p>Used to send HDMI control messages to other devices and manage them through
33091120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     * HDMI bus. It is also possible to communicate with other logical devices hosted in the same
33191120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     * system if the system is configured to host more than one type of HDMI-CEC logical devices.
33291120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     *
33391120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     * @return {@link HdmiTvClient} instance. {@code null} on failure.
33491120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim     */
33591120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim    @Nullable
33691120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim    public HdmiTvClient getTvClient() {
33761f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang        return (HdmiTvClient) getClient(HdmiDeviceInfo.DEVICE_TV);
33891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim    }
33978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim
34078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    /**
34178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim     * Listener used to get hotplug event from HDMI port.
34278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim     */
34378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    public interface HotplugEventListener {
34478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        void onReceived(HdmiHotplugEvent event);
34578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    }
34678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim
3472b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo    private final ArrayMap<HotplugEventListener, IHdmiHotplugEventListener>
3482b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo            mHotplugEventListeners = new ArrayMap<>();
3492b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo
35078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    /**
351119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim     * Listener used to get vendor-specific commands.
352119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim     */
353119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim    public interface VendorCommandListener {
354119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim        /**
355119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim         * Called when a vendor command is received.
356119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim         *
357119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim         * @param srcAddress source logical address
3580608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         * @param destAddress destination logical address
359119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim         * @param params vendor-specific parameters
360119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim         * @param hasVendorId {@code true} if the command is &lt;Vendor Command
361119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim         *        With ID&gt;. The first 3 bytes of params is vendor id.
362119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim         */
3630608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo        void onReceived(int srcAddress, int destAddress, byte[] params, boolean hasVendorId);
3640608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo
3650608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo        /**
3660608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         * The callback is called:
3670608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         * <ul>
3680608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         *     <li> before HdmiControlService is disabled.
3690608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         *     <li> after HdmiControlService is enabled and the local address is assigned.
3700608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         * </ul>
3710608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         * The client shouldn't hold the thread too long since this is a blocking call.
3720608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         *
3730608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         * @param enabled {@code true} if HdmiControlService is enabled.
3740608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         * @param reason the reason code why the state of HdmiControlService is changed.
3750608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         * @see #CONTROL_STATE_CHANGED_REASON_START
3760608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         * @see #CONTROL_STATE_CHANGED_REASON_SETTING
3770608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         * @see #CONTROL_STATE_CHANGED_REASON_WAKEUP
3780608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         * @see #CONTROL_STATE_CHANGED_REASON_STANDBY
3790608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo         */
3800608b9328b1c2f804ffb2d4165c34383d34bde2aYuncheol Heo        void onControlStateChanged(boolean enabled, int reason);
381119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim    }
382119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim
383119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim    /**
38478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim     * Adds a listener to get informed of {@link HdmiHotplugEvent}.
38578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim     *
38678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim     * <p>To stop getting the notification,
3879302a733b01c3ab4abd7911a286baf4833847d56Jinsuk Kim     * use {@link #removeHotplugEventListener(HotplugEventListener)}.
38878d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim     *
38978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim     * @param listener {@link HotplugEventListener} instance
3909302a733b01c3ab4abd7911a286baf4833847d56Jinsuk Kim     * @see HdmiControlManager#removeHotplugEventListener(HotplugEventListener)
39178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim     */
39278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    public void addHotplugEventListener(HotplugEventListener listener) {
39378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        if (mService == null) {
3942b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo            Log.e(TAG, "HdmiControlService is not available");
3952b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo            return;
3962b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo        }
3972b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo        if (mHotplugEventListeners.containsKey(listener)) {
3982b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo            Log.e(TAG, "listener is already registered");
39978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim            return;
40078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        }
4012b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo        IHdmiHotplugEventListener wrappedListener = getHotplugEventListenerWrapper(listener);
4022b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo        mHotplugEventListeners.put(listener, wrappedListener);
40378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        try {
4042b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo            mService.addHotplugEventListener(wrappedListener);
40578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        } catch (RemoteException e) {
406c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
40778d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        }
40878d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    }
40978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim
41078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    /**
41178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim     * Removes a listener to stop getting informed of {@link HdmiHotplugEvent}.
41278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim     *
41378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim     * @param listener {@link HotplugEventListener} instance to be removed
41478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim     */
4159302a733b01c3ab4abd7911a286baf4833847d56Jinsuk Kim    public void removeHotplugEventListener(HotplugEventListener listener) {
41678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        if (mService == null) {
4172b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo            Log.e(TAG, "HdmiControlService is not available");
4182b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo            return;
4192b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo        }
4202b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo        IHdmiHotplugEventListener wrappedListener = mHotplugEventListeners.remove(listener);
4212b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo        if (wrappedListener == null) {
4222b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo            Log.e(TAG, "tried to remove not-registered listener");
42378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim            return;
42478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        }
42578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        try {
4262b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo            mService.removeHotplugEventListener(wrappedListener);
42778d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        } catch (RemoteException e) {
428c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
42978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        }
43078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    }
43178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim
43278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    private IHdmiHotplugEventListener getHotplugEventListenerWrapper(
43378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim            final HotplugEventListener listener) {
43478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        return new IHdmiHotplugEventListener.Stub() {
435e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang            @Override
43678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim            public void onReceived(HdmiHotplugEvent event) {
43778d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim                listener.onReceived(event);;
43878d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim            }
43978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim        };
44078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim    }
44191120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim}
442