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