Home | History | Annotate | Download | only in hdmi
      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 
     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 
     65         /* package */ RecordSource(int sourceType, int extraDataSize) {
     66             mSourceType = sourceType;
     67             mExtraDataSize = extraDataSize;
     68         }
     69 
     70         /* package */ abstract int extraParamToByteArray(byte[] data, int index);
     71 
     72         /* package */ final int getDataSize(boolean includeType)  {
     73             return includeType ? mExtraDataSize + 1 : mExtraDataSize;
     74         }
     75 
     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      */
     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 
    110         private OwnSource() {
    111             super(RECORD_SOURCE_TYPE_OWN_SOURCE, EXTRA_DATA_SIZE);
    112         }
    113 
    114         @Override
    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 {
    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 
    191         public AribData(int transportStreamId, int serviceId, int originalNetworkId) {
    192             mTransportStreamId = transportStreamId;
    193             mServiceId = serviceId;
    194             mOriginalNetworkId = originalNetworkId;
    195         }
    196 
    197         @Override
    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 
    221         public AtscData(int transportStreamId, int programNumber) {
    222             mTransportStreamId = transportStreamId;
    223             mProgramNumber = programNumber;
    224         }
    225 
    226         @Override
    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 
    254         public DvbData(int transportStreamId, int serviceId, int originalNetworkId) {
    255             mTransportStreamId = transportStreamId;
    256             mServiceId = serviceId;
    257             mOriginalNetworkId = originalNetworkId;
    258         }
    259 
    260         @Override
    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 
    284         private ChannelIdentifier(int format, int majorNumber, int minorNumer) {
    285             mChannelNumberFormat = format;
    286             mMajorChannelNumber = majorNumber;
    287             mMinorChannelNumber = minorNumer;
    288         }
    289 
    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 
    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 
    321         public static DigitalChannelData ofOneNumber(int number) {
    322             return new DigitalChannelData(
    323                     new ChannelIdentifier(CHANNEL_NUMBER_FORMAT_1_PART, 0, number));
    324         }
    325 
    326         private DigitalChannelData(ChannelIdentifier id) {
    327             mChannelIdentifier = id;
    328         }
    329 
    330         @Override
    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      */
    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
    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
    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
    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 
    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
    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
    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 
    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
    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      */
    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 
    682         private ExternalPlugData(int plugNumber) {
    683             super(RECORD_SOURCE_TYPE_EXTERNAL_PLUG, EXTRA_DATA_SIZE);
    684             mPlugNumber = plugNumber;
    685         }
    686 
    687         @Override
    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      */
    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 
    726         private ExternalPhysicalAddress(int physicalAddress) {
    727             super(RECORD_SOURCE_TYPE_EXTERNAL_PHYSICAL_ADDRESS, EXTRA_DATA_SIZE);
    728             mPhysicalAddress = physicalAddress;
    729         }
    730 
    731         @Override
    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     // ---------------------------------------------------------------------------------------------
    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 
    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
    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