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     int mId;
149     LnbCallback mCallback;
150     Executor mExecutor;
151     Tuner mTuner;
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(int id)165     private Lnb(int id) {
166         mId = id;
167     }
168 
setCallback(Executor executor, @Nullable LnbCallback callback, Tuner tuner)169     void setCallback(Executor executor, @Nullable LnbCallback callback, Tuner tuner) {
170         mCallback = callback;
171         mExecutor = executor;
172         mTuner = tuner;
173     }
174 
onEvent(int eventType)175     private void onEvent(int eventType) {
176         if (mExecutor != null && mCallback != null) {
177             mExecutor.execute(() -> mCallback.onEvent(eventType));
178         }
179     }
180 
onDiseqcMessage(byte[] diseqcMessage)181     private void onDiseqcMessage(byte[] diseqcMessage) {
182         if (mExecutor != null && mCallback != null) {
183             mExecutor.execute(() -> mCallback.onDiseqcMessage(diseqcMessage));
184         }
185     }
186 
isClosed()187     /* package */ boolean isClosed() {
188         synchronized (mLock) {
189             return mIsClosed;
190         }
191     }
192 
193     /**
194      * Sets the LNB's power voltage.
195      *
196      * @param voltage the power voltage constant the Lnb to use.
197      * @return result status of the operation.
198      */
199     @Result
setVoltage(@oltage int voltage)200     public int setVoltage(@Voltage int voltage) {
201         synchronized (mLock) {
202             TunerUtils.checkResourceState(TAG, mIsClosed);
203             return nativeSetVoltage(voltage);
204         }
205     }
206 
207     /**
208      * Sets the LNB's tone mode.
209      *
210      * @param tone the tone mode the Lnb to use.
211      * @return result status of the operation.
212      */
213     @Result
setTone(@one int tone)214     public int setTone(@Tone int tone) {
215         synchronized (mLock) {
216             TunerUtils.checkResourceState(TAG, mIsClosed);
217             return nativeSetTone(tone);
218         }
219     }
220 
221     /**
222      * Selects the LNB's position.
223      *
224      * @param position the position the Lnb to use.
225      * @return result status of the operation.
226      */
227     @Result
setSatellitePosition(@osition int position)228     public int setSatellitePosition(@Position int position) {
229         synchronized (mLock) {
230             TunerUtils.checkResourceState(TAG, mIsClosed);
231             return nativeSetSatellitePosition(position);
232         }
233     }
234 
235     /**
236      * Sends DiSEqC (Digital Satellite Equipment Control) message.
237      *
238      * The response message from the device comes back through callback onDiseqcMessage.
239      *
240      * @param message a byte array of data for DiSEqC message which is specified by EUTELSAT Bus
241      *         Functional Specification Version 4.2.
242      *
243      * @return result status of the operation.
244      */
245     @Result
sendDiseqcMessage(@onNull byte[] message)246     public int sendDiseqcMessage(@NonNull byte[] message) {
247         synchronized (mLock) {
248             TunerUtils.checkResourceState(TAG, mIsClosed);
249             return nativeSendDiseqcMessage(message);
250         }
251     }
252 
253     /**
254      * Releases the LNB instance.
255      */
close()256     public void close() {
257         synchronized (mLock) {
258             if (mIsClosed) {
259                 return;
260             }
261             int res = nativeClose();
262             if (res != Tuner.RESULT_SUCCESS) {
263                 TunerUtils.throwExceptionForResult(res, "Failed to close LNB");
264             } else {
265                 mIsClosed = true;
266                 mTuner.releaseLnb();
267             }
268         }
269     }
270 }
271