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