HdmiControlManager.java revision 339227da7cf025ce4ae0c85ddc52643d63972321
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; 2478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim 2591120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim/** 2691120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * The {@link HdmiControlManager} class is used to send HDMI control messages 2791120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * to attached CEC devices. 2891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * 2991120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * <p>Provides various HDMI client instances that represent HDMI-CEC logical devices 3091120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * hosted in the system. {@link #getTvClient()}, for instance will return an 3191120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * {@link HdmiTvClient} object if the system is configured to host one. Android system 3291120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * can host more than one logical CEC devices. If multiple types are configured they 3391120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * all work as if they were independent logical devices running in the system. 3466d1eb285b129836d1b3c392ed609283c0dbf830Jinsuk Kim * 3566d1eb285b129836d1b3c392ed609283c0dbf830Jinsuk Kim * @hide 3691120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim */ 3766d1eb285b129836d1b3c392ed609283c0dbf830Jinsuk Kim@SystemApi 3891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kimpublic final class HdmiControlManager { 3991120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim @Nullable private final IHdmiControlService mService; 4091120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim 41c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim /** 42c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim * Broadcast Action: Display OSD message. 43c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim * <p>Send when the service has a message to display on screen for events 44c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim * that need user's attention such as ARC status change. 45e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang * <p>Always contains the extra fields {@link #EXTRA_MESSAGE_ID}. 46c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim * <p>Requires {@link android.Manifest.permission#HDMI_CEC} to receive. 47c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim */ 48c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 49c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim public static final String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE"; 50c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim 51339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang // --- Messages for ACTION_OSD_MESSAGE --- 52339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang /** 53339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang * Message that ARC enabled device is connected to invalid port (non-ARC port). 54339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang */ 55339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang public static final int OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT = 1; 56339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang 57c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim /** 58c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the ID of 59c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim * the message to display on screen. 60c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim */ 61c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim public static final String EXTRA_MESSAGE_ID = "android.hardware.hdmi.extra.MESSAGE_ID"; 62c7eba0f1db8928ca779933a564a06989e22a8532Jinsuk Kim 63c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim public static final int POWER_STATUS_UNKNOWN = -1; 64c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim public static final int POWER_STATUS_ON = 0; 65c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim public static final int POWER_STATUS_STANDBY = 1; 66c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim public static final int POWER_STATUS_TRANSIENT_TO_ON = 2; 67c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim public static final int POWER_STATUS_TRANSIENT_TO_STANDBY = 3; 68c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim 69c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim public static final int RESULT_SUCCESS = 0; 70c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim public static final int RESULT_TIMEOUT = 1; 71c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim public static final int RESULT_SOURCE_NOT_AVAILABLE = 2; 72c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim public static final int RESULT_TARGET_NOT_AVAILABLE = 3; 73c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim public static final int RESULT_ALREADY_IN_PROGRESS = 4; 74c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim public static final int RESULT_EXCEPTION = 5; 75c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim public static final int RESULT_INCORRECT_MODE = 6; 76b38cd68b240d99e8c8ae6ff1802a574696b420cdJinsuk Kim public static final int RESULT_COMMUNICATION_FAILED = 7; 77c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim 7861daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang public static final int DEVICE_EVENT_ADD_DEVICE = 1; 7961daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang public static final int DEVICE_EVENT_REMOVE_DEVICE = 2; 8061daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang public static final int DEVICE_EVENT_UPDATE_DEVICE = 3; 8161daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang 8212e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang // --- One Touch Recording success result 83b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** Recording currently selected source. Indicates the status of a recording. */ 8412e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_RECORDING_CURRENTLY_SELECTED_SOURCE = 0x01; 85b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** Recording Digital Service. Indicates the status of a recording. */ 8612e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE = 0x02; 87b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** Recording Analogue Service. Indicates the status of a recording. */ 8812e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_RECORDING_ANALOGUE_SERVICE = 0x03; 89b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** Recording External input. Indicates the status of a recording. */ 9012e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT = 0x04; 9112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang 9212e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang // --- One Touch Record failure result 93b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – unable to record Digital Service. No suitable tuner. */ 9412e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_UNABLE_DIGITAL_SERVICE = 0x05; 95b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – unable to record Analogue Service. No suitable tuner. */ 9612e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_UNABLE_ANALOGUE_SERVICE = 0x06; 97b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** 98b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang * No recording – unable to select required service. as suitable tuner, but the requested 99b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang * parameters are invalid or out of range for that tuner. 100b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang */ 10112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_UNABLE_SELECTED_SERVICE = 0x07; 102b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – invalid External plug number */ 10312e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PLUG_NUMBER = 0x09; 104b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – invalid External Physical Address */ 10512e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_INVALID_EXTERNAL_PHYSICAL_ADDRESS = 0x0A; 106b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – CA system not supported */ 10712e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_UNSUPPORTED_CA = 0x0B; 108b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No Recording – No or Insufficient CA Entitlements” */ 10912e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_NO_OR_INSUFFICIENT_CA_ENTITLEMENTS = 0x0C; 110b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – Not allowed to copy source. Source is “copy never”. */ 11112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_DISALLOW_TO_COPY = 0x0D; 112b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – No further copies allowed */ 11312e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_DISALLOW_TO_FUTHER_COPIES = 0x0E; 114b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – No media */ 11512e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_NO_MEDIA = 0x10; 116b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – playing */ 11712e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_PLAYING = 0x11; 118b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – already recording */ 11912e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_ALREADY_RECORDING = 0x12; 120b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – media protected */ 12112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_MEDIA_PROTECTED = 0x13; 122b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – no source signal */ 12312e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_NO_SOURCE_SIGNAL = 0x14; 124b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – media problem */ 12512e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_MEDIA_PROBLEM = 0x15; 126b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – not enough space available */ 12712e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_NOT_ENOUGH_SPACE = 0x16; 128b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – Parental Lock On */ 12912e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_PARENT_LOCK_ON = 0x17; 130b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** Recording terminated normally */ 13112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_RECORDING_TERMINATED_NORMALLY = 0x1A; 132b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** Recording has already terminated */ 13312e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_RECORDING_ALREADY_TERMINATED = 0x1B; 134b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording – other reason */ 13512e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_OTHER_REASON = 0x1F; 136b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang // From here extra message for recording that is not mentioned in CEC spec 137b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording. Previous recording request in progress. */ 13812e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_PREVIOUS_RECORDING_IN_PROGRESS = 0x30; 139b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** No recording. Please check recorder and connection. */ 14012e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION = 0x31; 141b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** Cannot record currently displayed source. */ 14212e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN = 0x32; 14312e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang /** CEC is disabled. */ 14412e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang public static final int ONE_TOUCH_RECORD_CEC_DISABLED = 0x33; 145b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang 14612e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang // --- Types for timer recording 147b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** Timer recording type for digital service source. */ 148b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang public static final int TIMER_RECORDING_TYPE_DIGITAL = 1; 149b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** Timer recording type for analogue service source. */ 150b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang public static final int TIMER_RECORDING_TYPE_ANALOGUE = 2; 151b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** Timer recording type for external source. */ 152b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang public static final int TIMER_RECORDING_TYPE_EXTERNAL = 3; 153b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang 154e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang // --- Timer Status Data 155e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Media Info] - Media present and not protected. */ 156e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_MEDIA_INFO_PRESENT_NOT_PROTECTED = 0x0; 157e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Media Info] - Media present, but protected. */ 158e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_MEDIA_INFO_PRESENT_PROTECTED = 0x1; 159e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Media Info] - Media not present. */ 160e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_MEDIA_INFO_NOT_PRESENT = 0x2; 161e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang 162e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Programmed Info] - Enough space available for recording. */ 163e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_PROGRAMMED_INFO_ENOUGH_SPACE = 0x8; 164e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Programmed Info] - Not enough space available for recording. */ 165e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_PROGRAMMED_INFO_NOT_ENOUGH_SPACE = 0x9; 166e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Programmed Info] - Might not enough space available for recording. */ 167e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_PROGRAMMED_INFO_MIGHT_NOT_ENOUGH_SPACE = 0xB; 168e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Programmed Info] - No media info available. */ 169e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_PROGRAMMED_INFO_NO_MEDIA_INFO = 0xA; 170e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang 171e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Not Programmed Error Info] - No free timer available. */ 172e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_NOT_PROGRAMMED_NO_FREE_TIME = 0x1; 173e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Not Programmed Error Info] - Date out of range. */ 174e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_NOT_PROGRAMMED_DATE_OUT_OF_RANGE = 0x2; 175e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Not Programmed Error Info] - Recording Sequence error. */ 176e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_SEQUENCE = 0x3; 177e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Not Programmed Error Info] - Invalid External Plug Number. */ 178e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_EXTERNAL_PLUG_NUMBER = 0x4; 179e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Not Programmed Error Info] - Invalid External Physical Address. */ 180e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_NOT_PROGRAMMED_INVALID_EXTERNAL_PHYSICAL_NUMBER = 0x5; 181e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Not Programmed Error Info] - CA system not supported. */ 182e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_NOT_PROGRAMMED_CA_NOT_SUPPORTED = 0x6; 183e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Not Programmed Error Info] - No or insufficient CA Entitlements. */ 184e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_NOT_PROGRAMMED_NO_CA_ENTITLEMENTS = 0x7; 185e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Not Programmed Error Info] - Does not support resolution. */ 186e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_NOT_PROGRAMMED_UNSUPPORTED_RESOLUTION = 0x8; 187e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Not Programmed Error Info] - Parental Lock On. */ 188e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_NOT_PROGRAMMED_PARENTAL_LOCK_ON= 0x9; 189e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Not Programmed Error Info] - Clock Failure. */ 190e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_NOT_PROGRAMMED_CLOCK_FAILURE = 0xA; 191e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** [Timer Status Data/Not Programmed Error Info] - Duplicate: already programmed. */ 192e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_STATUS_NOT_PROGRAMMED_DUPLICATED = 0xE; 193e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang 19412e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang // --- Extra result value for timer recording. 195e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** No extra error. */ 196e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_RECORDING_RESULT_EXTRA_NO_ERROR = 0x00; 19712e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang /** No timer recording - check recorder and connection. */ 198e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION = 0x01; 19912e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang /** No timer recording - cannot record selected source. */ 200e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE = 0x02; 20112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang /** CEC is disabled. */ 202e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int TIMER_RECORDING_RESULT_EXTRA_CEC_DISABLED = 0x03; 203e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang 204e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang // -- Timer cleared status data code used for result of onClearTimerRecordingResult. 205e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** Timer not cleared – recording. */ 206e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_RECORDING = 0x00; 207e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** Timer not cleared – no matching. */ 208e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_NO_MATCHING = 0x01; 209e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** Timer not cleared – no info available. */ 210e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int CLEAR_TIMER_STATUS_TIMER_NOT_CLEARED_NO_INFO_AVAILABLE = 0x02; 211e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** Timer cleared. */ 212e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int CLEAR_TIMER_STATUS_TIMER_CLEARED = 0x80; 213e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** Clear timer error - check recorder and connection. */ 214e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int CLEAR_TIMER_STATUS_CHECK_RECORDER_CONNECTION = 0xA0; 215e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** Clear timer error - cannot clear timer for selected source. */ 216e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE = 0xA1; 217e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang /** Clear timer error - CEC is disabled. */ 218e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public static final int CLEAR_TIMER_STATUS_CEC_DISABLE = 0xA2; 21912e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang 22078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim // True if we have a logical device of type playback hosted in the system. 22178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim private final boolean mHasPlaybackDevice; 22278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim // True if we have a logical device of type TV hosted in the system. 22378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim private final boolean mHasTvDevice; 22478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim 22591120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim /** 22691120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * @hide - hide this constructor because it has a parameter of type 22791120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * IHdmiControlService, which is a system private class. The right way 22891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * to create an instance of this class is using the factory 22991120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * Context.getSystemService. 23091120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim */ 23191120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim public HdmiControlManager(IHdmiControlService service) { 23291120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim mService = service; 23378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim int[] types = null; 23478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim if (mService != null) { 23578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim try { 23678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim types = mService.getSupportedTypes(); 23778d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } catch (RemoteException e) { 23878d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim // Do nothing. 23978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 24078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 24161f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang mHasTvDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_TV); 24261f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang mHasPlaybackDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_PLAYBACK); 24378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 24478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim 24578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim private static boolean hasDeviceType(int[] types, int type) { 24678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim if (types == null) { 24778d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim return false; 24878d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 24978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim for (int t : types) { 25078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim if (t == type) { 25178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim return true; 25278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 25378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 25478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim return false; 25591120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim } 25691120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim 25791120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim /** 2586ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim * Gets an object that represents an HDMI-CEC logical device of a specified type. 2596ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim * 2606ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim * @param type CEC device type 2616ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim * @return {@link HdmiClient} instance. {@code null} on failure. 26261f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang * See {@link HdmiDeviceInfo#DEVICE_PLAYBACK} 26361f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang * See {@link HdmiDeviceInfo#DEVICE_TV} 2646ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim */ 2656ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim @Nullable 2666ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim public HdmiClient getClient(int type) { 2676ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim if (mService == null) { 2686ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim return null; 2696ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim } 2706ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim switch (type) { 27161f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang case HdmiDeviceInfo.DEVICE_TV: 2726ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim return mHasTvDevice ? new HdmiTvClient(mService) : null; 27361f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang case HdmiDeviceInfo.DEVICE_PLAYBACK: 2746ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim return mHasPlaybackDevice ? new HdmiPlaybackClient(mService) : null; 2756ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim default: 2766ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim return null; 2776ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim } 2786ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim } 2796ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim 2806ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim /** 2816ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim * Gets an object that represents an HDMI-CEC logical device of type playback on the system. 28291120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * 28391120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * <p>Used to send HDMI control messages to other devices like TV or audio amplifier through 28491120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * HDMI bus. It is also possible to communicate with other logical devices hosted in the same 28591120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * system if the system is configured to host more than one type of HDMI-CEC logical devices. 28691120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * 28791120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * @return {@link HdmiPlaybackClient} instance. {@code null} on failure. 28891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim */ 28991120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim @Nullable 29091120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim public HdmiPlaybackClient getPlaybackClient() { 29161f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang return (HdmiPlaybackClient) getClient(HdmiDeviceInfo.DEVICE_PLAYBACK); 29291120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim } 29391120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim 29491120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim /** 2956ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim * Gets an object that represents an HDMI-CEC logical device of type TV on the system. 29691120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * 29791120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * <p>Used to send HDMI control messages to other devices and manage them through 29891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * HDMI bus. It is also possible to communicate with other logical devices hosted in the same 29991120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * system if the system is configured to host more than one type of HDMI-CEC logical devices. 30091120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * 30191120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * @return {@link HdmiTvClient} instance. {@code null} on failure. 30291120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim */ 30391120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim @Nullable 30491120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim public HdmiTvClient getTvClient() { 30561f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang return (HdmiTvClient) getClient(HdmiDeviceInfo.DEVICE_TV); 30691120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim } 30778d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim 30878d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim /** 30978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim * Listener used to get hotplug event from HDMI port. 31078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim */ 31178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim public interface HotplugEventListener { 31278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim void onReceived(HdmiHotplugEvent event); 31378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 31478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim 31578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim /** 316119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim * Listener used to get vendor-specific commands. 317119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim */ 318119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim public interface VendorCommandListener { 319119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim /** 320119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim * Called when a vendor command is received. 321119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim * 322119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim * @param srcAddress source logical address 323119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim * @param params vendor-specific parameters 324119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim * @param hasVendorId {@code true} if the command is <Vendor Command 325119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim * With ID>. The first 3 bytes of params is vendor id. 326119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim */ 327119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim void onReceived(int srcAddress, byte[] params, boolean hasVendorId); 328119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim } 329119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim 330119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim /** 33178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim * Adds a listener to get informed of {@link HdmiHotplugEvent}. 33278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim * 33378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim * <p>To stop getting the notification, 3349302a733b01c3ab4abd7911a286baf4833847d56Jinsuk Kim * use {@link #removeHotplugEventListener(HotplugEventListener)}. 33578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim * 33678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim * @param listener {@link HotplugEventListener} instance 3379302a733b01c3ab4abd7911a286baf4833847d56Jinsuk Kim * @see HdmiControlManager#removeHotplugEventListener(HotplugEventListener) 33878d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim */ 33978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim public void addHotplugEventListener(HotplugEventListener listener) { 34078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim if (mService == null) { 34178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim return; 34278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 34378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim try { 34478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim mService.addHotplugEventListener(getHotplugEventListenerWrapper(listener)); 34578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } catch (RemoteException e) { 34678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim // Do nothing. 34778d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 34878d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 34978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim 35078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim /** 35178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim * Removes a listener to stop getting informed of {@link HdmiHotplugEvent}. 35278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim * 35378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim * @param listener {@link HotplugEventListener} instance to be removed 35478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim */ 3559302a733b01c3ab4abd7911a286baf4833847d56Jinsuk Kim public void removeHotplugEventListener(HotplugEventListener listener) { 35678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim if (mService == null) { 35778d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim return; 35878d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 35978d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim try { 36078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim mService.removeHotplugEventListener(getHotplugEventListenerWrapper(listener)); 36178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } catch (RemoteException e) { 36278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim // Do nothing. 36378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 36478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 36578d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim 36678d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim private IHdmiHotplugEventListener getHotplugEventListenerWrapper( 36778d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim final HotplugEventListener listener) { 36878d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim return new IHdmiHotplugEventListener.Stub() { 369e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang @Override 37078d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim public void onReceived(HdmiHotplugEvent event) { 37178d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim listener.onReceived(event);; 37278d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 37378d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim }; 37478d695d8ba532214b02e7f18e0ccf89cf099163dJinsuk Kim } 37591120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim} 376