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 Kimpackage android.hardware.hdmi; 1791120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim 18e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jangimport android.annotation.NonNull; 1966d1eb285b129836d1b3c392ed609283c0dbf830Jinsuk Kimimport android.annotation.SystemApi; 2012e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jangimport android.hardware.hdmi.HdmiRecordSources.RecordSource; 2112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jangimport android.hardware.hdmi.HdmiTimerRecordSources.TimerRecordSource; 22a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.os.RemoteException; 23a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.util.Log; 2466d1eb285b129836d1b3c392ed609283c0dbf830Jinsuk Kim 252b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heoimport libcore.util.EmptyArray; 262b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo 27bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kimimport java.util.Collections; 28bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kimimport java.util.List; 29bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim 3091120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim/** 3191120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * HdmiTvClient represents HDMI-CEC logical device of type TV in the Android system 3291120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * which acts as TV/Display. It provides with methods that manage, interact with other 3391120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim * devices on the CEC bus. 3466d1eb285b129836d1b3c392ed609283c0dbf830Jinsuk Kim * 3566d1eb285b129836d1b3c392ed609283c0dbf830Jinsuk Kim * @hide 3691120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim */ 3766d1eb285b129836d1b3c392ed609283c0dbf830Jinsuk Kim@SystemApi 38119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kimpublic final class HdmiTvClient extends HdmiClient { 3991120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim private static final String TAG = "HdmiTvClient"; 4091120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim 41f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang /** 42b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim * Size of MHL register for vendor command 43f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang */ 44b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim public static final int VENDOR_DATA_SIZE = 16; 45f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang 462b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo /* package */ HdmiTvClient(IHdmiControlService service) { 47119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim super(service); 4891120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim } 49a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 50a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim // Factory method for HdmiTvClient. 51a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim // Declared package-private. Accessed by HdmiControlManager only. 522b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo /* package */ static HdmiTvClient create(IHdmiControlService service) { 53a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim return new HdmiTvClient(service); 54a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 55a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 56a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang @Override 57119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim public int getDeviceType() { 5861f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang return HdmiDeviceInfo.DEVICE_TV; 59119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim } 60119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim 61a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim /** 62a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * Callback interface used to get the result of {@link #deviceSelect}. 63a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim */ 64a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim public interface SelectCallback { 65a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim /** 66a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * Called when the operation is finished. 67a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * 68a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * @param result the result value of {@link #deviceSelect} 69a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim */ 70a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim void onComplete(int result); 71a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 72a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 73a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim /** 742b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo * Selects a CEC logical device to be a new active source. 75a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * 766ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim * @param logicalAddress logical address of the device to select 776ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim * @param callback callback to get the result with 786ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim * @throws {@link IllegalArgumentException} if the {@code callback} is null 79a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim */ 80e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public void deviceSelect(int logicalAddress, @NonNull SelectCallback callback) { 81e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang if (callback == null) { 82e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang throw new IllegalArgumentException("callback must not be null."); 83e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang } 84a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim try { 85a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim mService.deviceSelect(logicalAddress, getCallbackWrapper(callback)); 86a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } catch (RemoteException e) { 87a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim Log.e(TAG, "failed to select device: ", e); 88a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 89a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 90a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 91f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) { 92f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang return new IHdmiControlCallback.Stub() { 93f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang @Override 94f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang public void onComplete(int result) { 95f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang callback.onComplete(result); 96f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 97f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang }; 98f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 99f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang 10041d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang /** 1012b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo * Selects a HDMI port to be a new route path. 1026ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim * 1036ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim * @param portId HDMI port to select 1046ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim * @param callback callback to get the result with 1056ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim * @throws {@link IllegalArgumentException} if the {@code callback} is null 1066ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim */ 1076ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim public void portSelect(int portId, @NonNull SelectCallback callback) { 1086ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim if (callback == null) { 1096ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim throw new IllegalArgumentException("Callback must not be null"); 1106ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim } 1116ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim try { 1126ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim mService.portSelect(portId, getCallbackWrapper(callback)); 1136ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim } catch (RemoteException e) { 1146ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim Log.e(TAG, "failed to select port: ", e); 1156ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim } 1166ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim } 1176ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim 1186ffb03816f7410c001072a25c3e4161a2da4f501Jinsuk Kim /** 119d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim * Callback interface used to get the input change event. 120d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim */ 121d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim public interface InputChangeListener { 122d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim /** 123d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim * Called when the input was changed. 124d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim * 125d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim * @param info newly selected HDMI input 126d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim */ 127d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim void onChanged(HdmiDeviceInfo info); 128d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim } 129d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim 130d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim /** 1312b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo * Sets the listener used to get informed of the input change event. 132d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim * 133d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim * @param listener listener object 134d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim */ 135d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim public void setInputChangeListener(InputChangeListener listener) { 136d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim if (listener == null) { 137d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim throw new IllegalArgumentException("listener must not be null."); 138d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim } 139d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim try { 140d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim mService.setInputChangeListener(getListenerWrapper(listener)); 141d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim } catch (RemoteException e) { 142d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim Log.e("TAG", "Failed to set InputChangeListener:", e); 143d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim } 144d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim } 145d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim 146f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang private static IHdmiInputChangeListener getListenerWrapper(final InputChangeListener listener) { 147f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang return new IHdmiInputChangeListener.Stub() { 148f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang @Override 149f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang public void onChanged(HdmiDeviceInfo info) { 150f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang listener.onChanged(info); 151f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 152f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang }; 153f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 154f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang 155d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim /** 156bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim * Returns all the CEC devices connected to TV. 157bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim * 158bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim * @return list of {@link HdmiDeviceInfo} for connected CEC devices. 159bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim * Empty list is returned if there is none. 160bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim */ 161bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim public List<HdmiDeviceInfo> getDeviceList() { 162bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim try { 163bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim return mService.getDeviceList(); 164bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim } catch (RemoteException e) { 165bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim Log.e("TAG", "Failed to call getDeviceList():", e); 166bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim return Collections.<HdmiDeviceInfo>emptyList(); 167bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim } 168bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim } 169bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim 170bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim /** 1712b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo * Sets system audio volume 17241d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang * 17341d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang * @param oldIndex current volume index 17441d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang * @param newIndex volume index to be set 17541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang * @param maxIndex maximum volume index 17641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang */ 17741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang public void setSystemAudioVolume(int oldIndex, int newIndex, int maxIndex) { 17841d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang try { 17941d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang mService.setSystemAudioVolume(oldIndex, newIndex, maxIndex); 18041d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } catch (RemoteException e) { 18141d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang Log.e(TAG, "failed to set volume: ", e); 18241d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 18341d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 18441d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 18541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang /** 1862b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo * Sets system audio mute status 18741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang * 18841d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang * @param mute {@code true} if muted; otherwise, {@code false} 18941d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang */ 19041d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang public void setSystemAudioMute(boolean mute) { 19141d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang try { 19241d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang mService.setSystemAudioMute(mute); 19341d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } catch (RemoteException e) { 19441d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang Log.e(TAG, "failed to set mute: ", e); 19541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 19641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 19741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 198a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang /** 1992b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo * Sets record listener 20012e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang * 20112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang * @param listener 202a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang */ 203e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public void setRecordListener(@NonNull HdmiRecordListener listener) { 204e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang if (listener == null) { 205e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang throw new IllegalArgumentException("listener must not be null."); 206e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang } 207a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang try { 20812e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang mService.setHdmiRecordListener(getListenerWrapper(listener)); 209a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang } catch (RemoteException e) { 21012e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang Log.e(TAG, "failed to set record listener.", e); 211a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang } 212a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang } 213a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang 214f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang private static IHdmiRecordListener getListenerWrapper(final HdmiRecordListener callback) { 215f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang return new IHdmiRecordListener.Stub() { 216f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang @Override 217f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang public byte[] getOneTouchRecordSource(int recorderAddress) { 218f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang HdmiRecordSources.RecordSource source = 2192b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo callback.onOneTouchRecordSourceRequested(recorderAddress); 220f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang if (source == null) { 221f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang return EmptyArray.BYTE; 222f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 223f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang byte[] data = new byte[source.getDataSize(true)]; 224f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang source.toByteArray(true, data, 0); 225f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang return data; 226f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 227f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang 228f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang @Override 229326aef0c9402742e29c4503c857f93e75cf9a6ecJungshik Jang public void onOneTouchRecordResult(int recorderAddress, int result) { 230326aef0c9402742e29c4503c857f93e75cf9a6ecJungshik Jang callback.onOneTouchRecordResult(recorderAddress, result); 231f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 232f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang 233f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang @Override 234326aef0c9402742e29c4503c857f93e75cf9a6ecJungshik Jang public void onTimerRecordingResult(int recorderAddress, int result) { 235326aef0c9402742e29c4503c857f93e75cf9a6ecJungshik Jang callback.onTimerRecordingResult(recorderAddress, 236f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang HdmiRecordListener.TimerStatusData.parseFrom(result)); 237f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 238f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang 239f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang @Override 240326aef0c9402742e29c4503c857f93e75cf9a6ecJungshik Jang public void onClearTimerRecordingResult(int recorderAddress, int result) { 241326aef0c9402742e29c4503c857f93e75cf9a6ecJungshik Jang callback.onClearTimerRecordingResult(recorderAddress, result); 242f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 243f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang }; 244f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 245f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang 246a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang /** 2472b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo * Starts one touch recording with the given recorder address and recorder source. 248bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * <p> 249bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * Usage 250a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang * <pre> 251a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang * HdmiTvClient tvClient = ....; 252a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang * // for own source. 2532b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo * OwnSource ownSource = HdmiRecordSources.ofOwnSource(); 254bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * tvClient.startOneTouchRecord(recorderAddress, ownSource); 255a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang * </pre> 256a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang */ 257e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang public void startOneTouchRecord(int recorderAddress, @NonNull RecordSource source) { 258e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang if (source == null) { 259e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang throw new IllegalArgumentException("source must not be null."); 260e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang } 261e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang 262a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang try { 263a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang byte[] data = new byte[source.getDataSize(true)]; 264a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang source.toByteArray(true, data, 0); 265bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang mService.startOneTouchRecord(recorderAddress, data); 266bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang } catch (RemoteException e) { 267bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang Log.e(TAG, "failed to start record: ", e); 268bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang } 269bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang } 270bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang 271bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang /** 2722b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo * Stops one touch record. 273b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang * 274b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang * @param recorderAddress recorder address where recoding will be stopped 275b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang */ 276b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang public void stopOneTouchRecord(int recorderAddress) { 277b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang try { 278b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang mService.stopOneTouchRecord(recorderAddress); 279b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang } catch (RemoteException e) { 280b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang Log.e(TAG, "failed to stop record: ", e); 281b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang } 282b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang } 283b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang 284b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** 2852b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo * Starts timer recording with the given recoder address and recorder source. 286bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * <p> 287bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * Usage 288bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * <pre> 289bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * HdmiTvClient tvClient = ....; 290bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * // create timer info 291bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * TimerInfo timerInfo = HdmiTimerRecourdSources.timerInfoOf(...); 292bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * // for digital source. 293bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * DigitalServiceSource recordSource = HdmiRecordSources.ofDigitalService(...); 294bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * // create timer recording source. 295bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * TimerRecordSource source = HdmiTimerRecourdSources.ofDigitalSource(timerInfo, recordSource); 296bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * tvClient.startTimerRecording(recorderAddress, source); 297bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang * </pre> 298b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang * 299b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang * @param recorderAddress target recorder address 300b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang * @param sourceType type of record source. It should be one of 301b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang * {@link HdmiControlManager#TIMER_RECORDING_TYPE_DIGITAL}, 302b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang * {@link HdmiControlManager#TIMER_RECORDING_TYPE_ANALOGUE}, 303b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang * {@link HdmiControlManager#TIMER_RECORDING_TYPE_EXTERNAL}. 304b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang * @param source record source to be used 305b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang */ 306b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang public void startTimerRecording(int recorderAddress, int sourceType, TimerRecordSource source) { 307e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang if (source == null) { 308e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang throw new IllegalArgumentException("source must not be null."); 309e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang } 310e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang 311b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang checkTimerRecordingSourceType(sourceType); 312b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang 313b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang try { 314b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang byte[] data = new byte[source.getDataSize()]; 315b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang source.toByteArray(data, 0); 316b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang mService.startTimerRecording(recorderAddress, sourceType, data); 317b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang } catch (RemoteException e) { 318b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang Log.e(TAG, "failed to start record: ", e); 319b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang } 320b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang } 321b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang 322b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang private void checkTimerRecordingSourceType(int sourceType) { 323b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang switch (sourceType) { 324b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang case HdmiControlManager.TIMER_RECORDING_TYPE_DIGITAL: 325b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang case HdmiControlManager.TIMER_RECORDING_TYPE_ANALOGUE: 326b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang case HdmiControlManager.TIMER_RECORDING_TYPE_EXTERNAL: 327b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang break; 328b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang default: 329b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang throw new IllegalArgumentException("Invalid source type:" + sourceType); 330b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang } 331b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang } 332b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang 333b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang /** 3342b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo * Clears timer recording with the given recorder address and recording source. 335b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang * For more details, please refer {@link #startTimerRecording(int, int, TimerRecordSource)}. 336bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang */ 337b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang public void clearTimerRecording(int recorderAddress, int sourceType, TimerRecordSource source) { 338e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang if (source == null) { 339e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang throw new IllegalArgumentException("source must not be null."); 340e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang } 341e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang 342b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang checkTimerRecordingSourceType(sourceType); 343bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang try { 344bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang byte[] data = new byte[source.getDataSize()]; 345bffb0635aaaaf9140d9120e3f3d95a4f7391a0acJungshik Jang source.toByteArray(data, 0); 346b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang mService.clearTimerRecording(recorderAddress, sourceType, data); 347a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang } catch (RemoteException e) { 348a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang Log.e(TAG, "failed to start record: ", e); 349a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang } 350a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang } 351a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang 352f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang /** 353b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim * Interface used to get incoming MHL vendor command. 354f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang */ 355b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim public interface HdmiMhlVendorCommandListener { 356f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang void onReceived(int portId, int offset, int length, byte[] data); 357a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 358a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang 359f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang /** 3602b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo * Sets {@link HdmiMhlVendorCommandListener} to get incoming MHL vendor command. 361f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang * 362b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim * @param listener to receive incoming MHL vendor command 363f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang */ 364b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim public void setHdmiMhlVendorCommandListener(HdmiMhlVendorCommandListener listener) { 365f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang if (listener == null) { 366f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang throw new IllegalArgumentException("listener must not be null."); 367f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 368f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang try { 369b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim mService.addHdmiMhlVendorCommandListener(getListenerWrapper(listener)); 370f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } catch (RemoteException e) { 371b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim Log.e(TAG, "failed to set hdmi mhl vendor command listener: ", e); 372f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 373d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim } 374d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim 375b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim private IHdmiMhlVendorCommandListener getListenerWrapper( 376b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim final HdmiMhlVendorCommandListener listener) { 377b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim return new IHdmiMhlVendorCommandListener.Stub() { 378a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang @Override 379f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang public void onReceived(int portId, int offset, int length, byte[] data) { 380f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang listener.onReceived(portId, offset, length, data); 38112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang } 382f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang }; 383f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 38412e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang 385f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang /** 3862b0da5c4c84305f1d391dc78b85e244c9fd92456Yuncheol Heo * Sends MHL vendor command to the device connected to a port of the given portId. 387f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang * 388b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim * @param portId id of port to send MHL vendor command 389f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang * @param offset offset in the in given data 390f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang * @param length length of data. offset + length should be bound to length of data. 391b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim * @param data container for vendor command data. It should be 16 bytes. 392f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang * @throws IllegalArgumentException if the given parameters are invalid 393f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang */ 394b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim public void sendMhlVendorCommand(int portId, int offset, int length, byte[] data) { 395b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim if (data == null || data.length != VENDOR_DATA_SIZE) { 396b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim throw new IllegalArgumentException("Invalid vendor command data."); 397f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 398b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim if (offset < 0 || offset >= VENDOR_DATA_SIZE) { 399f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang throw new IllegalArgumentException("Invalid offset:" + offset); 400f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 401b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim if (length < 0 || offset + length > VENDOR_DATA_SIZE) { 402f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang throw new IllegalArgumentException("Invalid length:" + length); 403f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 404e5a9337ebe738633cf7b66141cdf76efcdc5754cJungshik Jang 405f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang try { 406b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim mService.sendMhlVendorCommand(portId, offset, length, data); 407f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } catch (RemoteException e) { 408b3fbf9dbe8d41d91efbac2118b676af74592257bJinsuk Kim Log.e(TAG, "failed to send vendor command: ", e); 409f424932cfb1b16b01a37500d09e295912700a51dJungshik Jang } 410a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang } 41191120c541ac0c8c5e256b75759c884b4d6d664fcJinsuk Kim} 412