HdmiTvClient.java revision 6ffb03816f7410c001072a25c3e4161a2da4f501
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package android.hardware.hdmi; 17 18import android.annotation.NonNull; 19import android.annotation.SystemApi; 20import android.hardware.hdmi.HdmiRecordSources.RecordSource; 21import android.hardware.hdmi.HdmiTimerRecordSources.TimerRecordSource; 22import android.os.RemoteException; 23import android.util.Log; 24 25import libcore.util.EmptyArray; 26 27/** 28 * HdmiTvClient represents HDMI-CEC logical device of type TV in the Android system 29 * which acts as TV/Display. It provides with methods that manage, interact with other 30 * devices on the CEC bus. 31 * 32 * @hide 33 */ 34@SystemApi 35public final class HdmiTvClient extends HdmiClient { 36 private static final String TAG = "HdmiTvClient"; 37 38 // Definitions used for setOption(). These should be in sync with the definition 39 // in hardware/libhardware/include/hardware/{hdmi_cec.h,mhl.h}. 40 41 /** 42 * TV gets turned on by incoming <Text/Image View On>. {@code ENABLED} by default. 43 * If set to {@code DISABLED}, TV won't turn on automatically. 44 */ 45 public static final int OPTION_CEC_AUTO_WAKEUP = 1; 46 47 /** 48 * If set to {@code DISABLED}, all CEC commands are discarded. 49 * 50 * <p> This option is for internal use only, not supposed to be used by other components. 51 * @hide 52 */ 53 public static final int OPTION_CEC_ENABLE = 2; 54 55 /** 56 * If set to {@code DISABLED}, system service yields control of CEC to sub-microcontroller. 57 * If {@code ENABLED}, it take the control back. 58 * 59 * <p> This option is for internal use only, not supposed to be used by other components. 60 * @hide 61 */ 62 public static final int OPTION_CEC_SERVICE_CONTROL = 3; 63 64 /** 65 * Put other devices to standby when TV goes to standby. {@code ENABLED} by default. 66 * If set to {@code DISABLED}, TV doesn't send <Standby> to other devices. 67 */ 68 public static final int OPTION_CEC_AUTO_DEVICE_OFF = 4; 69 70 /** If set to {@code DISABLED}, TV does not switch ports when mobile device is connected. */ 71 public static final int OPTION_MHL_INPUT_SWITCHING = 101; 72 73 /** If set to {@code ENABLED}, TV disables power charging for mobile device. */ 74 public static final int OPTION_MHL_POWER_CHARGE = 102; 75 76 /** 77 * If set to {@code DISABLED}, all MHL commands are discarded. 78 * 79 * <p> This option is for internal use only, not supposed to be used by other components. 80 * @hide 81 */ 82 public static final int OPTION_MHL_ENABLE = 103; 83 84 public static final int DISABLED = 0; 85 public static final int ENABLED = 1; 86 87 HdmiTvClient(IHdmiControlService service) { 88 super(service); 89 } 90 91 // Factory method for HdmiTvClient. 92 // Declared package-private. Accessed by HdmiControlManager only. 93 static HdmiTvClient create(IHdmiControlService service) { 94 return new HdmiTvClient(service); 95 } 96 97 @Override 98 public int getDeviceType() { 99 return HdmiCecDeviceInfo.DEVICE_TV; 100 } 101 102 /** 103 * Callback interface used to get the result of {@link #deviceSelect}. 104 */ 105 public interface SelectCallback { 106 /** 107 * Called when the operation is finished. 108 * 109 * @param result the result value of {@link #deviceSelect} 110 */ 111 void onComplete(int result); 112 } 113 114 /** 115 * Select a CEC logical device to be a new active source. 116 * 117 * @param logicalAddress logical address of the device to select 118 * @param callback callback to get the result with 119 * @throws {@link IllegalArgumentException} if the {@code callback} is null 120 */ 121 public void deviceSelect(int logicalAddress, @NonNull SelectCallback callback) { 122 if (callback == null) { 123 throw new IllegalArgumentException("callback must not be null."); 124 } 125 try { 126 mService.deviceSelect(logicalAddress, getCallbackWrapper(callback)); 127 } catch (RemoteException e) { 128 Log.e(TAG, "failed to select device: ", e); 129 } 130 } 131 132 /** 133 * Select a HDMI port to be a new route path. 134 * 135 * @param portId HDMI port to select 136 * @param callback callback to get the result with 137 * @throws {@link IllegalArgumentException} if the {@code callback} is null 138 */ 139 public void portSelect(int portId, @NonNull SelectCallback callback) { 140 if (callback == null) { 141 throw new IllegalArgumentException("Callback must not be null"); 142 } 143 try { 144 mService.portSelect(portId, getCallbackWrapper(callback)); 145 } catch (RemoteException e) { 146 Log.e(TAG, "failed to select port: ", e); 147 } 148 } 149 150 /** 151 * Set system audio volume 152 * 153 * @param oldIndex current volume index 154 * @param newIndex volume index to be set 155 * @param maxIndex maximum volume index 156 */ 157 public void setSystemAudioVolume(int oldIndex, int newIndex, int maxIndex) { 158 try { 159 mService.setSystemAudioVolume(oldIndex, newIndex, maxIndex); 160 } catch (RemoteException e) { 161 Log.e(TAG, "failed to set volume: ", e); 162 } 163 } 164 165 /** 166 * Set system audio mute status 167 * 168 * @param mute {@code true} if muted; otherwise, {@code false} 169 */ 170 public void setSystemAudioMute(boolean mute) { 171 try { 172 mService.setSystemAudioMute(mute); 173 } catch (RemoteException e) { 174 Log.e(TAG, "failed to set mute: ", e); 175 } 176 } 177 178 /** 179 * Set record listener 180 * 181 * @param listener 182 */ 183 public void setRecordListener(@NonNull HdmiRecordListener listener) { 184 if (listener == null) { 185 throw new IllegalArgumentException("listener must not be null."); 186 } 187 try { 188 mService.setHdmiRecordListener(getListenerWrapper(listener)); 189 } catch (RemoteException e) { 190 Log.e(TAG, "failed to set record listener.", e); 191 } 192 } 193 194 /** 195 * Start one touch recording with the given recorder address and recorder source. 196 * <p> 197 * Usage 198 * <pre> 199 * HdmiTvClient tvClient = ....; 200 * // for own source. 201 * OwnSource ownSource = ownHdmiRecordSources.ownSource(); 202 * tvClient.startOneTouchRecord(recorderAddress, ownSource); 203 * </pre> 204 */ 205 public void startOneTouchRecord(int recorderAddress, @NonNull RecordSource source) { 206 if (source == null) { 207 throw new IllegalArgumentException("source must not be null."); 208 } 209 210 try { 211 byte[] data = new byte[source.getDataSize(true)]; 212 source.toByteArray(true, data, 0); 213 mService.startOneTouchRecord(recorderAddress, data); 214 } catch (RemoteException e) { 215 Log.e(TAG, "failed to start record: ", e); 216 } 217 } 218 219 /** 220 * Stop one touch record. 221 * 222 * @param recorderAddress recorder address where recoding will be stopped 223 */ 224 public void stopOneTouchRecord(int recorderAddress) { 225 try { 226 mService.stopOneTouchRecord(recorderAddress); 227 } catch (RemoteException e) { 228 Log.e(TAG, "failed to stop record: ", e); 229 } 230 } 231 232 /** 233 * Start timer recording with the given recoder address and recorder source. 234 * <p> 235 * Usage 236 * <pre> 237 * HdmiTvClient tvClient = ....; 238 * // create timer info 239 * TimerInfo timerInfo = HdmiTimerRecourdSources.timerInfoOf(...); 240 * // for digital source. 241 * DigitalServiceSource recordSource = HdmiRecordSources.ofDigitalService(...); 242 * // create timer recording source. 243 * TimerRecordSource source = HdmiTimerRecourdSources.ofDigitalSource(timerInfo, recordSource); 244 * tvClient.startTimerRecording(recorderAddress, source); 245 * </pre> 246 * 247 * @param recorderAddress target recorder address 248 * @param sourceType type of record source. It should be one of 249 * {@link HdmiControlManager#TIMER_RECORDING_TYPE_DIGITAL}, 250 * {@link HdmiControlManager#TIMER_RECORDING_TYPE_ANALOGUE}, 251 * {@link HdmiControlManager#TIMER_RECORDING_TYPE_EXTERNAL}. 252 * @param source record source to be used 253 */ 254 public void startTimerRecording(int recorderAddress, int sourceType, TimerRecordSource source) { 255 if (source == null) { 256 throw new IllegalArgumentException("source must not be null."); 257 } 258 259 checkTimerRecordingSourceType(sourceType); 260 261 try { 262 byte[] data = new byte[source.getDataSize()]; 263 source.toByteArray(data, 0); 264 mService.startTimerRecording(recorderAddress, sourceType, data); 265 } catch (RemoteException e) { 266 Log.e(TAG, "failed to start record: ", e); 267 } 268 } 269 270 private void checkTimerRecordingSourceType(int sourceType) { 271 switch (sourceType) { 272 case HdmiControlManager.TIMER_RECORDING_TYPE_DIGITAL: 273 case HdmiControlManager.TIMER_RECORDING_TYPE_ANALOGUE: 274 case HdmiControlManager.TIMER_RECORDING_TYPE_EXTERNAL: 275 break; 276 default: 277 throw new IllegalArgumentException("Invalid source type:" + sourceType); 278 } 279 } 280 281 /** 282 * Clear timer recording with the given recorder address and recording source. 283 * For more details, please refer {@link #startTimerRecording(int, int, TimerRecordSource)}. 284 */ 285 public void clearTimerRecording(int recorderAddress, int sourceType, TimerRecordSource source) { 286 if (source == null) { 287 throw new IllegalArgumentException("source must not be null."); 288 } 289 290 checkTimerRecordingSourceType(sourceType); 291 try { 292 byte[] data = new byte[source.getDataSize()]; 293 source.toByteArray(data, 0); 294 mService.clearTimerRecording(recorderAddress, sourceType, data); 295 } catch (RemoteException e) { 296 Log.e(TAG, "failed to start record: ", e); 297 } 298 } 299 300 private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) { 301 return new IHdmiControlCallback.Stub() { 302 @Override 303 public void onComplete(int result) { 304 callback.onComplete(result); 305 } 306 }; 307 } 308 309 private static IHdmiRecordListener getListenerWrapper(final HdmiRecordListener callback) { 310 return new IHdmiRecordListener.Stub() { 311 @Override 312 public byte[] getOneTouchRecordSource(int recorderAddress) { 313 HdmiRecordSources.RecordSource source = 314 callback.getOneTouchRecordSource(recorderAddress); 315 if (source == null) { 316 return EmptyArray.BYTE; 317 } 318 byte[] data = new byte[source.getDataSize(true)]; 319 source.toByteArray(true, data, 0); 320 return data; 321 } 322 323 @Override 324 public void onOneTouchRecordResult(int result) { 325 callback.onOneTouchRecordResult(result); 326 } 327 328 @Override 329 public void onTimerRecordingResult(int result) { 330 callback.onTimerRecordingResult( 331 HdmiRecordListener.TimerStatusData.parseFrom(result)); 332 } 333 334 @Override 335 public void onClearTimerRecordingResult(int result) { 336 callback.onClearTimerRecordingResult(result); 337 } 338 }; 339 } 340} 341