1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.media.tv.tuner; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.hardware.tv.tuner.V1_0.Constants; 24 import android.media.tv.tuner.Tuner.Result; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 import java.util.concurrent.Executor; 29 30 /** 31 * LNB (low-noise block downconverter) for satellite tuner. 32 * 33 * A Tuner LNB (low-noise block downconverter) is used by satellite frontend to receive the 34 * microwave signal from the satellite, amplify it, and downconvert the frequency to a lower 35 * frequency. 36 * 37 * @hide 38 */ 39 @SystemApi 40 public class Lnb implements AutoCloseable { 41 /** @hide */ 42 @IntDef(prefix = "VOLTAGE_", 43 value = {VOLTAGE_NONE, VOLTAGE_5V, VOLTAGE_11V, VOLTAGE_12V, VOLTAGE_13V, VOLTAGE_14V, 44 VOLTAGE_15V, VOLTAGE_18V, VOLTAGE_19V}) 45 @Retention(RetentionPolicy.SOURCE) 46 public @interface Voltage {} 47 48 /** 49 * LNB power voltage not set. 50 */ 51 public static final int VOLTAGE_NONE = Constants.LnbVoltage.NONE; 52 /** 53 * LNB power voltage 5V. 54 */ 55 public static final int VOLTAGE_5V = Constants.LnbVoltage.VOLTAGE_5V; 56 /** 57 * LNB power voltage 11V. 58 */ 59 public static final int VOLTAGE_11V = Constants.LnbVoltage.VOLTAGE_11V; 60 /** 61 * LNB power voltage 12V. 62 */ 63 public static final int VOLTAGE_12V = Constants.LnbVoltage.VOLTAGE_12V; 64 /** 65 * LNB power voltage 13V. 66 */ 67 public static final int VOLTAGE_13V = Constants.LnbVoltage.VOLTAGE_13V; 68 /** 69 * LNB power voltage 14V. 70 */ 71 public static final int VOLTAGE_14V = Constants.LnbVoltage.VOLTAGE_14V; 72 /** 73 * LNB power voltage 15V. 74 */ 75 public static final int VOLTAGE_15V = Constants.LnbVoltage.VOLTAGE_15V; 76 /** 77 * LNB power voltage 18V. 78 */ 79 public static final int VOLTAGE_18V = Constants.LnbVoltage.VOLTAGE_18V; 80 /** 81 * LNB power voltage 19V. 82 */ 83 public static final int VOLTAGE_19V = Constants.LnbVoltage.VOLTAGE_19V; 84 85 /** @hide */ 86 @IntDef(prefix = "TONE_", 87 value = {TONE_NONE, TONE_CONTINUOUS}) 88 @Retention(RetentionPolicy.SOURCE) 89 public @interface Tone {} 90 91 /** 92 * LNB tone mode not set. 93 */ 94 public static final int TONE_NONE = Constants.LnbTone.NONE; 95 /** 96 * LNB continuous tone mode. 97 */ 98 public static final int TONE_CONTINUOUS = Constants.LnbTone.CONTINUOUS; 99 100 /** @hide */ 101 @IntDef(prefix = "POSITION_", 102 value = {POSITION_UNDEFINED, POSITION_A, POSITION_B}) 103 @Retention(RetentionPolicy.SOURCE) 104 public @interface Position {} 105 106 /** 107 * LNB position is not defined. 108 */ 109 public static final int POSITION_UNDEFINED = Constants.LnbPosition.UNDEFINED; 110 /** 111 * Position A of two-band LNBs 112 */ 113 public static final int POSITION_A = Constants.LnbPosition.POSITION_A; 114 /** 115 * Position B of two-band LNBs 116 */ 117 public static final int POSITION_B = Constants.LnbPosition.POSITION_B; 118 119 /** @hide */ 120 @Retention(RetentionPolicy.SOURCE) 121 @IntDef(prefix = "EVENT_TYPE_", 122 value = {EVENT_TYPE_DISEQC_RX_OVERFLOW, EVENT_TYPE_DISEQC_RX_TIMEOUT, 123 EVENT_TYPE_DISEQC_RX_PARITY_ERROR, EVENT_TYPE_LNB_OVERLOAD}) 124 public @interface EventType {} 125 126 /** 127 * Outgoing Diseqc message overflow. 128 */ 129 public static final int EVENT_TYPE_DISEQC_RX_OVERFLOW = 130 Constants.LnbEventType.DISEQC_RX_OVERFLOW; 131 /** 132 * Outgoing Diseqc message isn't delivered on time. 133 */ 134 public static final int EVENT_TYPE_DISEQC_RX_TIMEOUT = 135 Constants.LnbEventType.DISEQC_RX_TIMEOUT; 136 /** 137 * Incoming Diseqc message has parity error. 138 */ 139 public static final int EVENT_TYPE_DISEQC_RX_PARITY_ERROR = 140 Constants.LnbEventType.DISEQC_RX_PARITY_ERROR; 141 /** 142 * LNB is overload. 143 */ 144 public static final int EVENT_TYPE_LNB_OVERLOAD = Constants.LnbEventType.LNB_OVERLOAD; 145 146 private static final String TAG = "Lnb"; 147 148 LnbCallback mCallback; 149 Executor mExecutor; 150 Tuner mTuner; 151 private final Object mCallbackLock = new Object(); 152 153 nativeSetVoltage(int voltage)154 private native int nativeSetVoltage(int voltage); nativeSetTone(int tone)155 private native int nativeSetTone(int tone); nativeSetSatellitePosition(int position)156 private native int nativeSetSatellitePosition(int position); nativeSendDiseqcMessage(byte[] message)157 private native int nativeSendDiseqcMessage(byte[] message); nativeClose()158 private native int nativeClose(); 159 160 private long mNativeContext; 161 162 private Boolean mIsClosed = false; 163 private final Object mLock = new Object(); 164 Lnb()165 private Lnb() {} 166 setCallback(Executor executor, @Nullable LnbCallback callback, Tuner tuner)167 void setCallback(Executor executor, @Nullable LnbCallback callback, Tuner tuner) { 168 synchronized (mCallbackLock) { 169 mCallback = callback; 170 mExecutor = executor; 171 mTuner = tuner; 172 } 173 } 174 onEvent(int eventType)175 private void onEvent(int eventType) { 176 synchronized (mCallbackLock) { 177 if (mExecutor != null && mCallback != null) { 178 mExecutor.execute(() -> mCallback.onEvent(eventType)); 179 } 180 } 181 } 182 onDiseqcMessage(byte[] diseqcMessage)183 private void onDiseqcMessage(byte[] diseqcMessage) { 184 synchronized (mCallbackLock) { 185 if (mExecutor != null && mCallback != null) { 186 mExecutor.execute(() -> mCallback.onDiseqcMessage(diseqcMessage)); 187 } 188 } 189 } 190 isClosed()191 /* package */ boolean isClosed() { 192 synchronized (mLock) { 193 return mIsClosed; 194 } 195 } 196 197 /** 198 * Sets the LNB's power voltage. 199 * 200 * @param voltage the power voltage constant the Lnb to use. 201 * @return result status of the operation. 202 */ 203 @Result setVoltage(@oltage int voltage)204 public int setVoltage(@Voltage int voltage) { 205 synchronized (mLock) { 206 TunerUtils.checkResourceState(TAG, mIsClosed); 207 return nativeSetVoltage(voltage); 208 } 209 } 210 211 /** 212 * Sets the LNB's tone mode. 213 * 214 * @param tone the tone mode the Lnb to use. 215 * @return result status of the operation. 216 */ 217 @Result setTone(@one int tone)218 public int setTone(@Tone int tone) { 219 synchronized (mLock) { 220 TunerUtils.checkResourceState(TAG, mIsClosed); 221 return nativeSetTone(tone); 222 } 223 } 224 225 /** 226 * Selects the LNB's position. 227 * 228 * @param position the position the Lnb to use. 229 * @return result status of the operation. 230 */ 231 @Result setSatellitePosition(@osition int position)232 public int setSatellitePosition(@Position int position) { 233 synchronized (mLock) { 234 TunerUtils.checkResourceState(TAG, mIsClosed); 235 return nativeSetSatellitePosition(position); 236 } 237 } 238 239 /** 240 * Sends DiSEqC (Digital Satellite Equipment Control) message. 241 * 242 * The response message from the device comes back through callback onDiseqcMessage. 243 * 244 * @param message a byte array of data for DiSEqC message which is specified by EUTELSAT Bus 245 * Functional Specification Version 4.2. 246 * 247 * @return result status of the operation. 248 */ 249 @Result sendDiseqcMessage(@onNull byte[] message)250 public int sendDiseqcMessage(@NonNull byte[] message) { 251 synchronized (mLock) { 252 TunerUtils.checkResourceState(TAG, mIsClosed); 253 return nativeSendDiseqcMessage(message); 254 } 255 } 256 257 /** 258 * Releases the LNB instance. 259 */ close()260 public void close() { 261 synchronized (mLock) { 262 if (mIsClosed) { 263 return; 264 } 265 int res = nativeClose(); 266 if (res != Tuner.RESULT_SUCCESS) { 267 TunerUtils.throwExceptionForResult(res, "Failed to close LNB"); 268 } else { 269 mIsClosed = true; 270 mTuner.releaseLnb(); 271 } 272 } 273 } 274 } 275