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  */
16 
17 package android.hardware.hdmi;
18 
19 import android.annotation.Nullable;
20 import android.annotation.SystemApi;
21 import android.util.Log;
22 
23 /**
24  * Container for record source used for one touch record.
25  * Use one of helper method by source type.
26  * <ul>
27  * <li>Own source: {@link #ofOwnSource()}
28  * <li>Digital service(channel id): {@link #ofDigitalChannelId(int, DigitalChannelData)}
29  * <li>Digital service(ARIB): {@link #ofArib(int, AribData)}
30  * <li>Digital service(ATSC): {@link #ofAtsc(int, AtscData)}
31  * <li>Digital service(DVB): {@link #ofDvb(int, DvbData)}
32  * <li>Analogue: {@link #ofAnalogue(int, int, int)}
33  * <li>External plug: {@link #ofExternalPlug(int)}
34  * <li>External physical address: {@link #ofExternalPhysicalAddress(int)}.
35  * <ul>
36  *
37  * @hide
38  */
39 @SystemApi
40 public final class HdmiRecordSources {
41     private static final String TAG = "HdmiRecordSources";
42 
43     /** Record source type for "Own Source". */
44     private static final int RECORD_SOURCE_TYPE_OWN_SOURCE = 1;
45     /** Record source type for "Digital Service". */
46     private static final int RECORD_SOURCE_TYPE_DIGITAL_SERVICE = 2;
47     /** Record source type for "Analogue Service". */
48     private static final int RECORD_SOURCE_TYPE_ANALOGUE_SERVICE = 3;
49     /** Record source type for "Exteranl Plug". */
50     private static final int RECORD_SOURCE_TYPE_EXTERNAL_PLUG = 4;
51     /** Record source type for "External Physical Address". */
52     private static final int RECORD_SOURCE_TYPE_EXTERNAL_PHYSICAL_ADDRESS = 5;
53 
HdmiRecordSources()54     private HdmiRecordSources() {}
55 
56     /**
57      * Base class for each record source.
58      * @hide
59      */
60     @SystemApi
61     public static abstract class RecordSource {
62         /* package */ final int mSourceType;
63         /* package */ final int mExtraDataSize;
64 
RecordSource(int sourceType, int extraDataSize)65         /* package */ RecordSource(int sourceType, int extraDataSize) {
66             mSourceType = sourceType;
67             mExtraDataSize = extraDataSize;
68         }
69 
extraParamToByteArray(byte[] data, int index)70         /* package */ abstract int extraParamToByteArray(byte[] data, int index);
71 
getDataSize(boolean includeType)72         /* package */ final int getDataSize(boolean includeType)  {
73             return includeType ? mExtraDataSize + 1 : mExtraDataSize;
74         }
75 
toByteArray(boolean includeType, byte[] data, int index)76         /* package */ final int toByteArray(boolean includeType, byte[] data, int index) {
77             if (includeType) {
78                 // 1 to 8 bytes (depends on source).
79                 // {[Record Source Type]} |
80                 // {[Record Source Type] [Digital Service Identification]} |
81                 // {[Record Source Type] [Analogue Broadcast Type] [Analogue Frequency]
82                 // [Broadcast System]} |
83                 // {[Record Source Type] [External Plug]} |
84                 // {[Record Source Type] [External Physical Address]}
85                 // The first byte is used for record source type.
86                 data[index++] = (byte) mSourceType;
87             }
88             extraParamToByteArray(data, index);
89             return getDataSize(includeType);
90         }
91     }
92 
93     // ---------------------------------------------------------------------------------------------
94     // ---- Own source -----------------------------------------------------------------------------
95     // ---------------------------------------------------------------------------------------------
96     /**
97      * Creates {@link OwnSource} of own source.
98      */
ofOwnSource()99     public static OwnSource ofOwnSource() {
100         return new OwnSource();
101     }
102 
103     /**
104      * @hide
105      */
106     @SystemApi
107     public static final class OwnSource extends RecordSource {
108         private static final int EXTRA_DATA_SIZE = 0;
109 
OwnSource()110         private OwnSource() {
111             super(RECORD_SOURCE_TYPE_OWN_SOURCE, EXTRA_DATA_SIZE);
112         }
113 
114         @Override
extraParamToByteArray(byte[] data, int index)115         int extraParamToByteArray(byte[] data, int index) {
116             return 0;
117         }
118     }
119 
120 
121     // ---------------------------------------------------------------------------------------------
122     // ---- Digital service data -------------------------------------------------------------------
123     // ---------------------------------------------------------------------------------------------
124     /**
125      * Digital broadcast general types
126      */
127     /** @hide */
128     public static final int DIGITAL_BROADCAST_TYPE_ARIB = 0x0;
129     /** @hide */
130     public static final int DIGITAL_BROADCAST_TYPE_ATSC = 0x1;
131     /** @hide */
132     public static final int DIGITAL_BROADCAST_TYPE_DVB = 0x2;
133 
134     /**
135      * Digital broadcast specific types
136      */
137     /** @hide */
138     public static final int DIGITAL_BROADCAST_TYPE_ARIB_BS = 0x8;
139     /** @hide */
140     public static final int DIGITAL_BROADCAST_TYPE_ARIB_CS = 0x9;
141     /** @hide */
142     public static final int DIGITAL_BROADCAST_TYPE_ARIB_T = 0xA;
143     /** @hide */
144     public static final int DIGITAL_BROADCAST_TYPE_ATSC_CABLE = 0x10;
145     /** @hide */
146     public static final int DIGITAL_BROADCAST_TYPE_ATSC_SATELLITE = 0x11;
147     /** @hide */
148     public static final int DIGITAL_BROADCAST_TYPE_ATSC_TERRESTRIAL = 0x12;
149     /** @hide */
150     public static final int DIGITAL_BROADCAST_TYPE_DVB_C = 0x18;
151     /** @hide */
152     public static final int DIGITAL_BROADCAST_TYPE_DVB_S = 0x19;
153     /** @hide */
154     public static final int DIGITAL_BROADCAST_TYPE_DVB_S2 = 0x1A;
155     /** @hide */
156     public static final int DIGITAL_BROADCAST_TYPE_DVB_T = 0x1B;
157 
158     /** Channel number formats. */
159     private static final int CHANNEL_NUMBER_FORMAT_1_PART = 0x01;
160     private static final int CHANNEL_NUMBER_FORMAT_2_PART = 0x02;
161 
162     /**
163      * Interface for digital source identification.
164      */
165     private interface DigitalServiceIdentification {
toByteArray(byte[] data, int index)166         int toByteArray(byte[] data, int index);
167     }
168 
169     /**
170      * Digital service identification for ARIB.
171      * <p>
172      * It consists of the following fields
173      * <ul>
174      * <li>transport stream id: 2bytes
175      * <li>service id: 2bytes
176      * <li>original network id: 2bytes
177      * </ul>
178      * @hide
179      */
180     public static final class AribData implements DigitalServiceIdentification {
181         /** The transport_stream_ID of the transport stream carrying the required service */
182         private final int mTransportStreamId;
183         /** The service_ID of the required service */
184         private final int mServiceId;
185         /**
186          * The original_network_ID of the network carrying the transport stream for the required
187          * service
188          */
189         private final int mOriginalNetworkId;
190 
AribData(int transportStreamId, int serviceId, int originalNetworkId)191         public AribData(int transportStreamId, int serviceId, int originalNetworkId) {
192             mTransportStreamId = transportStreamId;
193             mServiceId = serviceId;
194             mOriginalNetworkId = originalNetworkId;
195         }
196 
197         @Override
toByteArray(byte[] data, int index)198         public int toByteArray(byte[] data, int index) {
199             return threeFieldsToSixBytes(mTransportStreamId, mServiceId, mOriginalNetworkId, data,
200                     index);
201         }
202     }
203 
204     /**
205      * Digital service identification for ATSC.
206      * <p>
207      * It consists of the following fields
208      * <ul>
209      * <li>transport stream id: 2bytes
210      * <li>program number: 2bytes
211      * <li>reserved: 2bytes
212      * </ul>
213      * @hide
214      */
215     public static final class AtscData implements DigitalServiceIdentification {
216         /** The transport_stream_ID of the transport stream carrying the required service */
217         private final int mTransportStreamId;
218         /** The Program_number of the required service */
219         private final int mProgramNumber;
220 
AtscData(int transportStreamId, int programNumber)221         public AtscData(int transportStreamId, int programNumber) {
222             mTransportStreamId = transportStreamId;
223             mProgramNumber = programNumber;
224         }
225 
226         @Override
toByteArray(byte[] data, int index)227         public int toByteArray(byte[] data, int index) {
228             return threeFieldsToSixBytes(mTransportStreamId, mProgramNumber, 0, data, index);
229         }
230     }
231 
232     /**
233      * Digital service identification for DVB.
234      * <p>
235      * It consists of the following fields
236      * <ul>
237      * <li>transport stream id: 2bytes
238      * <li>service id: 2bytes
239      * <li>original network id: 2bytes
240      * </ul>
241      * @hide
242      */
243     public static final class DvbData implements DigitalServiceIdentification {
244         /** The transport_stream_ID of the transport stream carrying the required service */
245         private final int mTransportStreamId;
246         /** The service_ID of the required service */
247         private final int mServiceId;
248         /**
249          * The original_network_ID of the network carrying the transport stream for the required
250          * service
251          */
252         private final int mOriginalNetworkId;
253 
DvbData(int transportStreamId, int serviceId, int originalNetworkId)254         public DvbData(int transportStreamId, int serviceId, int originalNetworkId) {
255             mTransportStreamId = transportStreamId;
256             mServiceId = serviceId;
257             mOriginalNetworkId = originalNetworkId;
258         }
259 
260         @Override
toByteArray(byte[] data, int index)261         public int toByteArray(byte[] data, int index) {
262             return threeFieldsToSixBytes(mTransportStreamId, mServiceId, mOriginalNetworkId, data,
263                     index);
264         }
265     }
266 
267     /**
268      * Identifies a 1-part Logical or Virtual Channel Number or a 2-part Major and Minor channel
269      * combination.
270      */
271     private static final class ChannelIdentifier {
272         /** Identifies Channel Format */
273         private final int mChannelNumberFormat;
274         /**
275          * Major Channel Number (if Channel Number Format is 2-part). If format is
276          * CHANNEL_NUMBER_FORMAT_1_PART, this will be ignored(0).
277          */
278         private final int mMajorChannelNumber;
279         /**
280          * 1-part Channel Number, or a Minor Channel Number (if Channel Number Format is 2-part).
281          */
282         private final int mMinorChannelNumber;
283 
ChannelIdentifier(int format, int majorNumber, int minorNumer)284         private ChannelIdentifier(int format, int majorNumber, int minorNumer) {
285             mChannelNumberFormat = format;
286             mMajorChannelNumber = majorNumber;
287             mMinorChannelNumber = minorNumer;
288         }
289 
toByteArray(byte[] data, int index)290         private int toByteArray(byte[] data, int index) {
291             // The first 6 bits for format, the 10 bits for major number.
292             data[index] = (byte) (((mChannelNumberFormat << 2) | (mMajorChannelNumber >>> 8) & 0x3));
293             data[index + 1] = (byte) (mMajorChannelNumber & 0xFF);
294             // Minor number uses the next 16 bits.
295             shortToByteArray((short) mMinorChannelNumber, data, index + 2);
296             return 4;
297         }
298     }
299 
300     /**
301      * Digital channel id.
302      * <p>
303      * It consists of the following fields
304      * <ul>
305      * <li>channel number format: 6bits
306      * <li>major number: 10bits
307      * <li>minor number: 16bits
308      * <li>reserved: 2bytes
309      * </ul>
310      * @hide
311      */
312     public static final class DigitalChannelData implements DigitalServiceIdentification {
313         /** Identifies the logical or virtual channel number of a service. */
314         private final ChannelIdentifier mChannelIdentifier;
315 
ofTwoNumbers(int majorNumber, int minorNumber)316         public static DigitalChannelData ofTwoNumbers(int majorNumber, int minorNumber) {
317             return new DigitalChannelData(
318                     new ChannelIdentifier(CHANNEL_NUMBER_FORMAT_2_PART, majorNumber, minorNumber));
319         }
320 
ofOneNumber(int number)321         public static DigitalChannelData ofOneNumber(int number) {
322             return new DigitalChannelData(
323                     new ChannelIdentifier(CHANNEL_NUMBER_FORMAT_1_PART, 0, number));
324         }
325 
DigitalChannelData(ChannelIdentifier id)326         private DigitalChannelData(ChannelIdentifier id) {
327             mChannelIdentifier = id;
328         }
329 
330         @Override
toByteArray(byte[] data, int index)331         public int toByteArray(byte[] data, int index) {
332             mChannelIdentifier.toByteArray(data, index);
333             // The last 2 bytes is reserved for future use.
334             data[index + 4] = 0;
335             data[index + 5] = 0;
336             return 6;
337         }
338     }
339 
340     /**
341      * Creates {@link DigitalServiceSource} with channel type.
342      *
343      * @param broadcastSystem digital broadcast system. It should be one of
344      *            <ul>
345      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB}
346      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC}
347      *            <li>{@link #DIGITAL_BROADCAST_TYPE_DVB}
348      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB_BS}
349      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB_CS}
350      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB_T}
351      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC_CABLE}
352      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC_SATELLITE}
353      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC_TERRESTRIAL}
354      *            <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_C}
355      *            <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_S}
356      *            <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_S2}
357      *            <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_T}
358      *            </ul>
359      * @hide
360      */
ofDigitalChannelId(int broadcastSystem, DigitalChannelData data)361     public static DigitalServiceSource ofDigitalChannelId(int broadcastSystem,
362             DigitalChannelData data) {
363         if (data == null) {
364             throw new IllegalArgumentException("data should not be null.");
365         }
366         switch (broadcastSystem) {
367             case DIGITAL_BROADCAST_TYPE_ARIB:
368             case DIGITAL_BROADCAST_TYPE_ATSC:
369             case DIGITAL_BROADCAST_TYPE_DVB:
370             case DIGITAL_BROADCAST_TYPE_ARIB_BS:
371             case DIGITAL_BROADCAST_TYPE_ARIB_CS:
372             case DIGITAL_BROADCAST_TYPE_ARIB_T:
373             case DIGITAL_BROADCAST_TYPE_ATSC_CABLE:
374             case DIGITAL_BROADCAST_TYPE_ATSC_SATELLITE:
375             case DIGITAL_BROADCAST_TYPE_ATSC_TERRESTRIAL:
376             case DIGITAL_BROADCAST_TYPE_DVB_C:
377             case DIGITAL_BROADCAST_TYPE_DVB_S:
378             case DIGITAL_BROADCAST_TYPE_DVB_S2:
379             case DIGITAL_BROADCAST_TYPE_DVB_T:
380                 return new DigitalServiceSource(
381                         DigitalServiceSource.DIGITAL_SERVICE_IDENTIFIED_BY_CHANNEL,
382                         broadcastSystem,
383                         data);
384             default:
385                 Log.w(TAG, "Invalid broadcast type:" + broadcastSystem);
386                 throw new IllegalArgumentException(
387                         "Invalid broadcast system value:" + broadcastSystem);
388         }
389     }
390 
391     /**
392      * Creates {@link DigitalServiceSource} of ARIB type.
393      *
394      * @param aribType ARIB type. It should be one of
395      *            <ul>
396      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB}
397      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB_BS}
398      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB_CS}
399      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ARIB_T}
400      *            </ul>
401      * @hide
402      */
403     @Nullable
ofArib(int aribType, AribData data)404     public static DigitalServiceSource ofArib(int aribType, AribData data) {
405         if (data == null) {
406             throw new IllegalArgumentException("data should not be null.");
407         }
408         switch (aribType) {
409             case DIGITAL_BROADCAST_TYPE_ARIB:
410             case DIGITAL_BROADCAST_TYPE_ARIB_BS:
411             case DIGITAL_BROADCAST_TYPE_ARIB_CS:
412             case DIGITAL_BROADCAST_TYPE_ARIB_T:
413                 return new DigitalServiceSource(
414                         DigitalServiceSource.DIGITAL_SERVICE_IDENTIFIED_BY_DIGITAL_ID,
415                         aribType, data);
416             default:
417                 Log.w(TAG, "Invalid ARIB type:" + aribType);
418                 throw new IllegalArgumentException("type should not be null.");
419         }
420     }
421 
422     /**
423      * Creates {@link DigitalServiceSource} of ATSC type.
424      *
425      * @param atscType ATSC type. It should be one of
426      *            <ul>
427      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC}
428      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC_CABLE}
429      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC_SATELLITE}
430      *            <li>{@link #DIGITAL_BROADCAST_TYPE_ATSC_TERRESTRIAL}
431      *            </ul>
432      * @hide
433      */
434     @Nullable
ofAtsc(int atscType, AtscData data)435     public static DigitalServiceSource ofAtsc(int atscType, AtscData data) {
436         if (data == null) {
437             throw new IllegalArgumentException("data should not be null.");
438         }
439         switch (atscType) {
440             case DIGITAL_BROADCAST_TYPE_ATSC:
441             case DIGITAL_BROADCAST_TYPE_ATSC_CABLE:
442             case DIGITAL_BROADCAST_TYPE_ATSC_SATELLITE:
443             case DIGITAL_BROADCAST_TYPE_ATSC_TERRESTRIAL:
444                 return new DigitalServiceSource(
445                         DigitalServiceSource.DIGITAL_SERVICE_IDENTIFIED_BY_DIGITAL_ID,
446                         atscType, data);
447             default:
448                 Log.w(TAG, "Invalid ATSC type:" + atscType);
449                 throw new IllegalArgumentException("Invalid ATSC type:" + atscType);
450         }
451     }
452 
453     /**
454      * Creates {@link DigitalServiceSource} of ATSC type.
455      *
456      * @param dvbType DVB type. It should be one of
457      *            <ul>
458      *            <li>{@link #DIGITAL_BROADCAST_TYPE_DVB}
459      *            <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_C}
460      *            <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_S}
461      *            <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_S2}
462      *            <li>{@link #DIGITAL_BROADCAST_TYPE_DVB_T}
463      *            </ul>
464      * @hide
465      */
466     @Nullable
ofDvb(int dvbType, DvbData data)467     public static DigitalServiceSource ofDvb(int dvbType, DvbData data) {
468         if (data == null) {
469             throw new IllegalArgumentException("data should not be null.");
470         }
471         switch (dvbType) {
472             case DIGITAL_BROADCAST_TYPE_DVB:
473             case DIGITAL_BROADCAST_TYPE_DVB_C:
474             case DIGITAL_BROADCAST_TYPE_DVB_S:
475             case DIGITAL_BROADCAST_TYPE_DVB_S2:
476             case DIGITAL_BROADCAST_TYPE_DVB_T:
477                 return new DigitalServiceSource(
478                         DigitalServiceSource.DIGITAL_SERVICE_IDENTIFIED_BY_DIGITAL_ID,
479                         dvbType, data);
480             default:
481                 Log.w(TAG, "Invalid DVB type:" + dvbType);
482                 throw new IllegalArgumentException("Invalid DVB type:" + dvbType);
483         }
484     }
485 
486     /**
487      * Record source container for "Digital Service".
488      * <ul>
489      * <li>[Record Source Type] - 1 byte
490      * <li>[Digital Identification] - 7 bytes
491      * </ul>
492      * @hide
493      */
494     @SystemApi
495     public static final class DigitalServiceSource extends RecordSource {
496         /** Indicates that a service is identified by digital service IDs. */
497         private static final int DIGITAL_SERVICE_IDENTIFIED_BY_DIGITAL_ID = 0;
498         /** Indicates that a service is identified by a logical or virtual channel number. */
499         private static final int DIGITAL_SERVICE_IDENTIFIED_BY_CHANNEL = 1;
500 
501         static final int EXTRA_DATA_SIZE = 7;
502 
503         /**
504          * Type of identification. It should be one of DIGITAL_SERVICE_IDENTIFIED_BY_DIGITAL_ID and
505          * DIGITAL_SERVICE_IDENTIFIED_BY_CHANNEL
506          */
507         private final int mIdentificationMethod;
508         /**
509          * Indicates the Digital Broadcast System of required service. This is present irrespective
510          * of the state of [Service Identification Method].
511          */
512         private final int mBroadcastSystem;
513 
514         /**
515          * Extra parameter for digital service identification.
516          */
517         private final DigitalServiceIdentification mIdentification;
518 
DigitalServiceSource(int identificatinoMethod, int broadcastSystem, DigitalServiceIdentification identification)519         private DigitalServiceSource(int identificatinoMethod, int broadcastSystem,
520                 DigitalServiceIdentification identification) {
521             super(RECORD_SOURCE_TYPE_DIGITAL_SERVICE, EXTRA_DATA_SIZE);
522             mIdentificationMethod = identificatinoMethod;
523             mBroadcastSystem = broadcastSystem;
524             mIdentification = identification;
525         }
526 
527         @Override
extraParamToByteArray(byte[] data, int index)528         int extraParamToByteArray(byte[] data, int index) {
529             data[index] = (byte) ((mIdentificationMethod << 7) | (mBroadcastSystem & 0x7F));
530             mIdentification.toByteArray(data, index + 1);
531             return EXTRA_DATA_SIZE;
532 
533         }
534     }
535 
536 
537     // ---------------------------------------------------------------------------------------------
538     // ---- Analogue service data ------------------------------------------------------------------
539     // ---------------------------------------------------------------------------------------------
540     /**
541      * Analogue broadcast types.
542      */
543     /** @hide */
544     public static final int ANALOGUE_BROADCAST_TYPE_CABLE = 0x0;
545     /** @hide */
546     public static final int ANALOGUE_BROADCAST_TYPE_SATELLITE = 0x1;
547     /** @hide */
548     public static final int ANALOGUE_BROADCAST_TYPE_TERRESTRIAL = 0x2;
549 
550     /**
551      * Broadcast system values.
552      */
553     /** @hide */
554     public static final int BROADCAST_SYSTEM_PAL_BG = 0;
555     /** @hide */
556     public static final int BROADCAST_SYSTEM_SECAM_LP = 1;
557     /** @hide */
558     public static final int BROADCAST_SYSTEM_PAL_M = 2;
559     /** @hide */
560     public static final int BROADCAST_SYSTEM_NTSC_M = 3;
561     /** @hide */
562     public static final int BROADCAST_SYSTEM_PAL_I = 4;
563     /** @hide */
564     public static final int BROADCAST_SYSTEM_SECAM_DK = 5;
565     /** @hide */
566     public static final int BROADCAST_SYSTEM_SECAM_BG = 6;
567     /** @hide */
568     public static final int BROADCAST_SYSTEM_SECAM_L = 7;
569     /** @hide */
570     public static final int BROADCAST_SYSTEM_PAL_DK = 8;
571     /** @hide */
572     public static final int BROADCAST_SYSTEM_PAL_OTHER_SYSTEM = 31;
573 
574     /**
575      * Creates {@link AnalogueServiceSource} of analogue service.
576      *
577      * @param broadcastType
578      * @param frequency
579      * @param broadcastSystem
580      * @hide
581      */
582     @Nullable
ofAnalogue(int broadcastType, int frequency, int broadcastSystem)583     public static AnalogueServiceSource ofAnalogue(int broadcastType, int frequency,
584             int broadcastSystem){
585         if (broadcastType < ANALOGUE_BROADCAST_TYPE_CABLE
586                 || broadcastType > ANALOGUE_BROADCAST_TYPE_TERRESTRIAL) {
587             Log.w(TAG, "Invalid Broadcast type:" + broadcastType);
588             throw new IllegalArgumentException("Invalid Broadcast type:" + broadcastType);
589         }
590         if (frequency < 0 || frequency > 0xFFFF) {
591             Log.w(TAG, "Invalid frequency value[0x0000-0xFFFF]:" + frequency);
592             throw new IllegalArgumentException(
593                     "Invalid frequency value[0x0000-0xFFFF]:" + frequency);
594         }
595         if (broadcastSystem < BROADCAST_SYSTEM_PAL_BG
596                 || broadcastSystem > BROADCAST_SYSTEM_PAL_OTHER_SYSTEM) {
597 
598             Log.w(TAG, "Invalid Broadcast system:" + broadcastSystem);
599             throw new IllegalArgumentException(
600                     "Invalid Broadcast system:" + broadcastSystem);
601         }
602 
603         return new AnalogueServiceSource(broadcastType, frequency, broadcastSystem);
604     }
605 
606     /**
607      * Record source for analogue service data. It consists of
608      * <ul>
609      * <li>[Record Source Type] - 1 byte
610      * <li>[Analogue Broadcast Type] - 1 byte
611      * <li>[Analogue Frequency] - 2 bytes
612      * <li>[Broadcast System] - 1 byte
613      * </ul>
614      * @hide
615      */
616     @SystemApi
617     public static final class AnalogueServiceSource extends RecordSource {
618         /* package */ static final int EXTRA_DATA_SIZE = 4;
619 
620         /** Indicates the Analogue broadcast type. */
621         private final int mBroadcastType;
622         /** Used to specify the frequency used by an analogue tuner. 0x0000<N<0xFFFF. */
623         private final int mFrequency;
624         /**
625          * This specifies information about the color system, the sound carrier and the
626          * IF-frequency.
627          */
628         private final int mBroadcastSystem;
629 
AnalogueServiceSource(int broadcastType, int frequency, int broadcastSystem)630         private AnalogueServiceSource(int broadcastType, int frequency, int broadcastSystem) {
631             super(RECORD_SOURCE_TYPE_ANALOGUE_SERVICE, EXTRA_DATA_SIZE);
632             mBroadcastType = broadcastType;
633             mFrequency = frequency;
634             mBroadcastSystem = broadcastSystem;
635         }
636 
637         @Override
extraParamToByteArray(byte[] data, int index)638         /* package */ int extraParamToByteArray(byte[] data, int index) {
639             // [Analogue Broadcast Type] - 1 byte
640             data[index] = (byte) mBroadcastType;
641             // [Analogue Frequency] - 2 bytes
642             shortToByteArray((short) mFrequency, data, index + 1);
643             // [Broadcast System] - 1 byte
644             data[index + 3] = (byte) mBroadcastSystem;
645             return EXTRA_DATA_SIZE;
646         }
647     }
648 
649 
650     // ---------------------------------------------------------------------------------------------
651     // ---- External plug data ---------------------------------------------------------------------
652     // ---------------------------------------------------------------------------------------------
653     /**
654      * Creates {@link ExternalPlugData} of external plug type.
655      *
656      * @param plugNumber plug number. It should be in range of [1, 255]
657      * @hide
658      */
ofExternalPlug(int plugNumber)659     public static ExternalPlugData ofExternalPlug(int plugNumber) {
660         if (plugNumber < 1 || plugNumber > 255) {
661             Log.w(TAG, "Invalid plug number[1-255]" + plugNumber);
662             throw new IllegalArgumentException("Invalid plug number[1-255]" + plugNumber);
663         }
664         return new ExternalPlugData(plugNumber);
665     }
666 
667     /**
668      * Record source for external plug (external non-HDMI device connect) type.
669      * <ul>
670      * <li>[Record Source Type] - 1 byte
671      * <li>[External Plug] - 1 byte
672      * </ul>
673      * @hide
674      */
675     @SystemApi
676     public static final class ExternalPlugData extends RecordSource {
677         static final int EXTRA_DATA_SIZE = 1;
678 
679         /** External Plug number on the Recording Device. */
680         private final int mPlugNumber;
681 
ExternalPlugData(int plugNumber)682         private ExternalPlugData(int plugNumber) {
683             super(RECORD_SOURCE_TYPE_EXTERNAL_PLUG, EXTRA_DATA_SIZE);
684             mPlugNumber = plugNumber;
685         }
686 
687         @Override
extraParamToByteArray(byte[] data, int index)688         int extraParamToByteArray(byte[] data, int index) {
689             data[index] = (byte) mPlugNumber;
690             return EXTRA_DATA_SIZE;
691         }
692     }
693 
694     // ---------------------------------------------------------------------------------------------
695     // ---- External physical address --------------------------------------------------------------
696     // ---------------------------------------------------------------------------------------------
697     /**
698      * Creates {@link ExternalPhysicalAddress} of external physical address.
699      *
700      * @param physicalAddress
701      * @hide
702      */
ofExternalPhysicalAddress(int physicalAddress)703     public static ExternalPhysicalAddress ofExternalPhysicalAddress(int physicalAddress) {
704         if ((physicalAddress & ~0xFFFF) != 0) {
705             Log.w(TAG, "Invalid physical address:" + physicalAddress);
706             throw new IllegalArgumentException("Invalid physical address:" + physicalAddress);
707         }
708 
709         return new ExternalPhysicalAddress(physicalAddress);
710     }
711 
712     /**
713      * Record source for external physical address.
714      * <ul>
715      * <li>[Record Source Type] - 1 byte
716      * <li>[Physical address] - 2 byte
717      * </ul>
718      * @hide
719      */
720     @SystemApi
721     public static final class ExternalPhysicalAddress extends RecordSource {
722         static final int EXTRA_DATA_SIZE = 2;
723 
724         private final int mPhysicalAddress;
725 
ExternalPhysicalAddress(int physicalAddress)726         private ExternalPhysicalAddress(int physicalAddress) {
727             super(RECORD_SOURCE_TYPE_EXTERNAL_PHYSICAL_ADDRESS, EXTRA_DATA_SIZE);
728             mPhysicalAddress = physicalAddress;
729         }
730 
731         @Override
extraParamToByteArray(byte[] data, int index)732         int extraParamToByteArray(byte[] data, int index) {
733             shortToByteArray((short) mPhysicalAddress, data, index);
734             return EXTRA_DATA_SIZE;
735         }
736     }
737 
738 
739     // ---------------------------------------------------------------------------------------------
740     // ------- Helper methods ----------------------------------------------------------------------
741     // ---------------------------------------------------------------------------------------------
threeFieldsToSixBytes(int first, int second, int third, byte[] data, int index)742     private static int threeFieldsToSixBytes(int first, int second, int third, byte[] data,
743             int index) {
744         shortToByteArray((short) first, data, index);
745         shortToByteArray((short) second, data, index + 2);
746         shortToByteArray((short) third, data, index + 4);
747         return 6;
748     }
749 
shortToByteArray(short value, byte[] byteArray, int index)750     private static int shortToByteArray(short value, byte[] byteArray, int index) {
751         byteArray[index] = (byte) ((value >>> 8) & 0xFF);
752         byteArray[index + 1] = (byte) (value & 0xFF);
753         return 2;
754     }
755 
756     /**
757      * Checks the byte array of record source.
758      * @hide
759      */
760     @SystemApi
checkRecordSource(byte[] recordSource)761     public static boolean checkRecordSource(byte[] recordSource) {
762         if (recordSource == null || recordSource.length == 0) return false;
763 
764         int recordSourceType = recordSource[0];
765         int extraDataSize = recordSource.length - 1;
766         switch (recordSourceType) {
767             case RECORD_SOURCE_TYPE_OWN_SOURCE:
768                 return extraDataSize == OwnSource.EXTRA_DATA_SIZE;
769             case RECORD_SOURCE_TYPE_DIGITAL_SERVICE:
770                 return extraDataSize == DigitalServiceSource.EXTRA_DATA_SIZE;
771             case RECORD_SOURCE_TYPE_ANALOGUE_SERVICE:
772                 return extraDataSize == AnalogueServiceSource.EXTRA_DATA_SIZE;
773             case RECORD_SOURCE_TYPE_EXTERNAL_PLUG:
774                 return extraDataSize == ExternalPlugData.EXTRA_DATA_SIZE;
775             case RECORD_SOURCE_TYPE_EXTERNAL_PHYSICAL_ADDRESS:
776                 return extraDataSize == ExternalPhysicalAddress.EXTRA_DATA_SIZE;
777             default:
778                 return false;
779         }
780     }
781 }
782