Home | History | Annotate | Download | only in radio
      1 /**
      2  * Copyright (C) 2015 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.radio;
     18 
     19 import android.annotation.SystemApi;
     20 import android.content.Context;
     21 import android.os.Handler;
     22 import android.os.Parcel;
     23 import android.os.Parcelable;
     24 import java.util.List;
     25 import java.util.Arrays;
     26 
     27 /**
     28  * The RadioManager class allows to control a broadcast radio tuner present on the device.
     29  * It provides data structures and methods to query for available radio modules, list their
     30  * properties and open an interface to control tuning operations and receive callbacks when
     31  * asynchronous operations complete or events occur.
     32  * @hide
     33  */
     34 @SystemApi
     35 public class RadioManager {
     36 
     37     /** Method return status: successful operation */
     38     public static final int STATUS_OK = 0;
     39     /** Method return status: unspecified error */
     40     public static final int STATUS_ERROR = Integer.MIN_VALUE;
     41     /** Method return status: permission denied */
     42     public static final int STATUS_PERMISSION_DENIED = -1;
     43     /** Method return status: initialization failure */
     44     public static final int STATUS_NO_INIT = -19;
     45     /** Method return status: invalid argument provided */
     46     public static final int STATUS_BAD_VALUE = -22;
     47     /** Method return status: cannot reach service */
     48     public static final int STATUS_DEAD_OBJECT = -32;
     49     /** Method return status: invalid or out of sequence operation */
     50     public static final int STATUS_INVALID_OPERATION = -38;
     51     /** Method return status: time out before operation completion */
     52     public static final int STATUS_TIMED_OUT = -110;
     53 
     54 
     55     // keep in sync with radio_class_t in /system/core/incluse/system/radio.h
     56     /** Radio module class supporting FM (including HD radio) and AM */
     57     public static final int CLASS_AM_FM = 0;
     58     /** Radio module class supporting satellite radio */
     59     public static final int CLASS_SAT = 1;
     60     /** Radio module class supporting Digital terrestrial radio */
     61     public static final int CLASS_DT = 2;
     62 
     63     // keep in sync with radio_band_t in /system/core/incluse/system/radio.h
     64     /** AM radio band (LW/MW/SW).
     65      * @see BandDescriptor */
     66     public static final int BAND_AM = 0;
     67     /** FM radio band.
     68      * @see BandDescriptor */
     69     public static final int BAND_FM = 1;
     70     /** FM HD radio or DRM  band.
     71      * @see BandDescriptor */
     72     public static final int BAND_FM_HD = 2;
     73     /** AM HD radio or DRM band.
     74      * @see BandDescriptor */
     75     public static final int BAND_AM_HD = 3;
     76 
     77     // keep in sync with radio_region_t in /system/core/incluse/system/radio.h
     78     /** Africa, Europe.
     79      * @see BandDescriptor */
     80     public static final int REGION_ITU_1  = 0;
     81     /** Americas.
     82      * @see BandDescriptor */
     83     public static final int REGION_ITU_2  = 1;
     84     /** Russia.
     85      * @see BandDescriptor */
     86     public static final int REGION_OIRT   = 2;
     87     /** Japan.
     88      * @see BandDescriptor */
     89     public static final int REGION_JAPAN  = 3;
     90     /** Korea.
     91      * @see BandDescriptor */
     92     public static final int REGION_KOREA  = 4;
     93 
     94     /*****************************************************************************
     95      * Lists properties, options and radio bands supported by a given broadcast radio module.
     96      * Each module has a unique ID used to address it when calling RadioManager APIs.
     97      * Module properties are returned by {@link #listModules(List <ModuleProperties>)} method.
     98      ****************************************************************************/
     99     public static class ModuleProperties implements Parcelable {
    100 
    101         private final int mId;
    102         private final int mClassId;
    103         private final String mImplementor;
    104         private final String mProduct;
    105         private final String mVersion;
    106         private final String mSerial;
    107         private final int mNumTuners;
    108         private final int mNumAudioSources;
    109         private final boolean mIsCaptureSupported;
    110         private final BandDescriptor[] mBands;
    111 
    112         ModuleProperties(int id, int classId, String implementor, String product, String version,
    113                 String serial, int numTuners, int numAudioSources, boolean isCaptureSupported,
    114                 BandDescriptor[] bands) {
    115             mId = id;
    116             mClassId = classId;
    117             mImplementor = implementor;
    118             mProduct = product;
    119             mVersion = version;
    120             mSerial = serial;
    121             mNumTuners = numTuners;
    122             mNumAudioSources = numAudioSources;
    123             mIsCaptureSupported = isCaptureSupported;
    124             mBands = bands;
    125         }
    126 
    127 
    128         /** Unique module identifier provided by the native service.
    129          * For use with {@link #openTuner(int, BandConfig, boolean, Callback, Handler)}.
    130          * @return the radio module unique identifier.
    131          */
    132         public int getId() {
    133             return mId;
    134         }
    135 
    136         /** Module class identifier: {@link #CLASS_AM_FM}, {@link #CLASS_SAT}, {@link #CLASS_DT}
    137          * @return the radio module class identifier.
    138          */
    139         public int getClassId() {
    140             return mClassId;
    141         }
    142 
    143         /** Human readable broadcast radio module implementor
    144          * @return the name of the radio module implementator.
    145          */
    146         public String getImplementor() {
    147             return mImplementor;
    148         }
    149 
    150         /** Human readable broadcast radio module product name
    151          * @return the radio module product name.
    152          */
    153         public String getProduct() {
    154             return mProduct;
    155         }
    156 
    157         /** Human readable broadcast radio module version number
    158          * @return the radio module version.
    159          */
    160         public String getVersion() {
    161             return mVersion;
    162         }
    163 
    164         /** Radio module serial number.
    165          * Can be used for subscription services.
    166          * @return the radio module serial number.
    167          */
    168         public String getSerial() {
    169             return mSerial;
    170         }
    171 
    172         /** Number of tuners available.
    173          * This is the number of tuners that can be open simultaneously.
    174          * @return the number of tuners supported.
    175          */
    176         public int getNumTuners() {
    177             return mNumTuners;
    178         }
    179 
    180         /** Number tuner audio sources available. Must be less or equal to getNumTuners().
    181          * When more than one tuner is supported, one is usually for playback and has one
    182          * associated audio source and the other is for pre scanning and building a
    183          * program list.
    184          * @return the number of audio sources available.
    185          */
    186         public int getNumAudioSources() {
    187             return mNumAudioSources;
    188         }
    189 
    190         /** {@code true} if audio capture is possible from radio tuner output.
    191          * This indicates if routing to audio devices not connected to the same HAL as the FM radio
    192          * is possible (e.g. to USB) or DAR (Digital Audio Recorder) feature can be implemented.
    193          * @return {@code true} if audio capture is possible, {@code false} otherwise.
    194          */
    195         public boolean isCaptureSupported() {
    196             return mIsCaptureSupported;
    197         }
    198 
    199         /** List of descriptors for all bands supported by this module.
    200          * @return an array of {@link BandDescriptor}.
    201          */
    202         public BandDescriptor[] getBands() {
    203             return mBands;
    204         }
    205 
    206         private ModuleProperties(Parcel in) {
    207             mId = in.readInt();
    208             mClassId = in.readInt();
    209             mImplementor = in.readString();
    210             mProduct = in.readString();
    211             mVersion = in.readString();
    212             mSerial = in.readString();
    213             mNumTuners = in.readInt();
    214             mNumAudioSources = in.readInt();
    215             mIsCaptureSupported = in.readInt() == 1;
    216             Parcelable[] tmp = in.readParcelableArray(BandDescriptor.class.getClassLoader());
    217             mBands = new BandDescriptor[tmp.length];
    218             for (int i = 0; i < tmp.length; i++) {
    219                 mBands[i] = (BandDescriptor) tmp[i];
    220             }
    221         }
    222 
    223         public static final Parcelable.Creator<ModuleProperties> CREATOR
    224                 = new Parcelable.Creator<ModuleProperties>() {
    225             public ModuleProperties createFromParcel(Parcel in) {
    226                 return new ModuleProperties(in);
    227             }
    228 
    229             public ModuleProperties[] newArray(int size) {
    230                 return new ModuleProperties[size];
    231             }
    232         };
    233 
    234         @Override
    235         public void writeToParcel(Parcel dest, int flags) {
    236             dest.writeInt(mId);
    237             dest.writeInt(mClassId);
    238             dest.writeString(mImplementor);
    239             dest.writeString(mProduct);
    240             dest.writeString(mVersion);
    241             dest.writeString(mSerial);
    242             dest.writeInt(mNumTuners);
    243             dest.writeInt(mNumAudioSources);
    244             dest.writeInt(mIsCaptureSupported ? 1 : 0);
    245             dest.writeParcelableArray(mBands, flags);
    246         }
    247 
    248         @Override
    249         public int describeContents() {
    250             return 0;
    251         }
    252 
    253         @Override
    254         public String toString() {
    255             return "ModuleProperties [mId=" + mId + ", mClassId=" + mClassId
    256                     + ", mImplementor=" + mImplementor + ", mProduct=" + mProduct
    257                     + ", mVersion=" + mVersion + ", mSerial=" + mSerial
    258                     + ", mNumTuners=" + mNumTuners
    259                     + ", mNumAudioSources=" + mNumAudioSources
    260                     + ", mIsCaptureSupported=" + mIsCaptureSupported
    261                     + ", mBands=" + Arrays.toString(mBands) + "]";
    262         }
    263 
    264         @Override
    265         public int hashCode() {
    266             final int prime = 31;
    267             int result = 1;
    268             result = prime * result + mId;
    269             result = prime * result + mClassId;
    270             result = prime * result + ((mImplementor == null) ? 0 : mImplementor.hashCode());
    271             result = prime * result + ((mProduct == null) ? 0 : mProduct.hashCode());
    272             result = prime * result + ((mVersion == null) ? 0 : mVersion.hashCode());
    273             result = prime * result + ((mSerial == null) ? 0 : mSerial.hashCode());
    274             result = prime * result + mNumTuners;
    275             result = prime * result + mNumAudioSources;
    276             result = prime * result + (mIsCaptureSupported ? 1 : 0);
    277             result = prime * result + Arrays.hashCode(mBands);
    278             return result;
    279         }
    280 
    281         @Override
    282         public boolean equals(Object obj) {
    283             if (this == obj)
    284                 return true;
    285             if (!(obj instanceof ModuleProperties))
    286                 return false;
    287             ModuleProperties other = (ModuleProperties) obj;
    288             if (mId != other.getId())
    289                 return false;
    290             if (mClassId != other.getClassId())
    291                 return false;
    292             if (mImplementor == null) {
    293                 if (other.getImplementor() != null)
    294                     return false;
    295             } else if (!mImplementor.equals(other.getImplementor()))
    296                 return false;
    297             if (mProduct == null) {
    298                 if (other.getProduct() != null)
    299                     return false;
    300             } else if (!mProduct.equals(other.getProduct()))
    301                 return false;
    302             if (mVersion == null) {
    303                 if (other.getVersion() != null)
    304                     return false;
    305             } else if (!mVersion.equals(other.getVersion()))
    306                 return false;
    307             if (mSerial == null) {
    308                 if (other.getSerial() != null)
    309                     return false;
    310             } else if (!mSerial.equals(other.getSerial()))
    311                 return false;
    312             if (mNumTuners != other.getNumTuners())
    313                 return false;
    314             if (mNumAudioSources != other.getNumAudioSources())
    315                 return false;
    316             if (mIsCaptureSupported != other.isCaptureSupported())
    317                 return false;
    318             if (!Arrays.equals(mBands, other.getBands()))
    319                 return false;
    320             return true;
    321         }
    322     }
    323 
    324     /** Radio band descriptor: an element in ModuleProperties bands array.
    325      * It is either an instance of {@link FmBandDescriptor} or {@link AmBandDescriptor} */
    326     public static class BandDescriptor implements Parcelable {
    327 
    328         private final int mRegion;
    329         private final int mType;
    330         private final int mLowerLimit;
    331         private final int mUpperLimit;
    332         private final int mSpacing;
    333 
    334         BandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing) {
    335             mRegion = region;
    336             mType = type;
    337             mLowerLimit = lowerLimit;
    338             mUpperLimit = upperLimit;
    339             mSpacing = spacing;
    340         }
    341 
    342         /** Region this band applies to. E.g. {@link #REGION_ITU_1}
    343          * @return the region this band is associated to.
    344          */
    345         public int getRegion() {
    346             return mRegion;
    347         }
    348         /** Band type, e.g {@link #BAND_FM}. Defines the subclass this descriptor can be cast to:
    349          * <ul>
    350          *  <li>{@link #BAND_FM} or {@link #BAND_FM_HD} cast to {@link FmBandDescriptor}, </li>
    351          *  <li>{@link #BAND_AM} cast to {@link AmBandDescriptor}, </li>
    352          * </ul>
    353          * @return the band type.
    354          */
    355         public int getType() {
    356             return mType;
    357         }
    358         /** Lower band limit expressed in units according to band type.
    359          * Currently all defined band types express channels as frequency in kHz
    360          * @return the lower band limit.
    361          */
    362         public int getLowerLimit() {
    363             return mLowerLimit;
    364         }
    365         /** Upper band limit expressed in units according to band type.
    366          * Currently all defined band types express channels as frequency in kHz
    367          * @return the upper band limit.
    368          */
    369         public int getUpperLimit() {
    370             return mUpperLimit;
    371         }
    372         /** Channel spacing in units according to band type.
    373          * Currently all defined band types express channels as frequency in kHz
    374          * @return the channel spacing.
    375          */
    376         public int getSpacing() {
    377             return mSpacing;
    378         }
    379 
    380         private BandDescriptor(Parcel in) {
    381             mRegion = in.readInt();
    382             mType = in.readInt();
    383             mLowerLimit = in.readInt();
    384             mUpperLimit = in.readInt();
    385             mSpacing = in.readInt();
    386         }
    387 
    388         public static final Parcelable.Creator<BandDescriptor> CREATOR
    389                 = new Parcelable.Creator<BandDescriptor>() {
    390             public BandDescriptor createFromParcel(Parcel in) {
    391                 return new BandDescriptor(in);
    392             }
    393 
    394             public BandDescriptor[] newArray(int size) {
    395                 return new BandDescriptor[size];
    396             }
    397         };
    398 
    399         @Override
    400         public void writeToParcel(Parcel dest, int flags) {
    401             dest.writeInt(mRegion);
    402             dest.writeInt(mType);
    403             dest.writeInt(mLowerLimit);
    404             dest.writeInt(mUpperLimit);
    405             dest.writeInt(mSpacing);
    406         }
    407 
    408         @Override
    409         public int describeContents() {
    410             return 0;
    411         }
    412 
    413         @Override
    414         public String toString() {
    415             return "BandDescriptor [mRegion=" + mRegion + ", mType=" + mType + ", mLowerLimit="
    416                     + mLowerLimit + ", mUpperLimit=" + mUpperLimit + ", mSpacing=" + mSpacing + "]";
    417         }
    418 
    419         @Override
    420         public int hashCode() {
    421             final int prime = 31;
    422             int result = 1;
    423             result = prime * result + mRegion;
    424             result = prime * result + mType;
    425             result = prime * result + mLowerLimit;
    426             result = prime * result + mUpperLimit;
    427             result = prime * result + mSpacing;
    428             return result;
    429         }
    430 
    431         @Override
    432         public boolean equals(Object obj) {
    433             if (this == obj)
    434                 return true;
    435             if (!(obj instanceof BandDescriptor))
    436                 return false;
    437             BandDescriptor other = (BandDescriptor) obj;
    438             if (mRegion != other.getRegion())
    439                 return false;
    440             if (mType != other.getType())
    441                 return false;
    442             if (mLowerLimit != other.getLowerLimit())
    443                 return false;
    444             if (mUpperLimit != other.getUpperLimit())
    445                 return false;
    446             if (mSpacing != other.getSpacing())
    447                 return false;
    448             return true;
    449         }
    450     }
    451 
    452     /** FM band descriptor
    453      * @see #BAND_FM
    454      * @see #BAND_FM_HD */
    455     public static class FmBandDescriptor extends BandDescriptor {
    456         private final boolean mStereo;
    457         private final boolean mRds;
    458         private final boolean mTa;
    459         private final boolean mAf;
    460 
    461         FmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing,
    462                 boolean stereo, boolean rds, boolean ta, boolean af) {
    463             super(region, type, lowerLimit, upperLimit, spacing);
    464             mStereo = stereo;
    465             mRds = rds;
    466             mTa = ta;
    467             mAf = af;
    468         }
    469 
    470         /** Stereo is supported
    471          * @return {@code true} if stereo is supported, {@code false} otherwise.
    472          */
    473         public boolean isStereoSupported() {
    474             return mStereo;
    475         }
    476         /** RDS or RBDS(if region is ITU2) is supported
    477          * @return {@code true} if RDS or RBDS is supported, {@code false} otherwise.
    478          */
    479         public boolean isRdsSupported() {
    480             return mRds;
    481         }
    482         /** Traffic announcement is supported
    483          * @return {@code true} if TA is supported, {@code false} otherwise.
    484          */
    485         public boolean isTaSupported() {
    486             return mTa;
    487         }
    488         /** Alternate Frequency Switching is supported
    489          * @return {@code true} if AF switching is supported, {@code false} otherwise.
    490          */
    491         public boolean isAfSupported() {
    492             return mAf;
    493         }
    494 
    495         /* Parcelable implementation */
    496         private FmBandDescriptor(Parcel in) {
    497             super(in);
    498             mStereo = in.readByte() == 1;
    499             mRds = in.readByte() == 1;
    500             mTa = in.readByte() == 1;
    501             mAf = in.readByte() == 1;
    502         }
    503 
    504         public static final Parcelable.Creator<FmBandDescriptor> CREATOR
    505                 = new Parcelable.Creator<FmBandDescriptor>() {
    506             public FmBandDescriptor createFromParcel(Parcel in) {
    507                 return new FmBandDescriptor(in);
    508             }
    509 
    510             public FmBandDescriptor[] newArray(int size) {
    511                 return new FmBandDescriptor[size];
    512             }
    513         };
    514 
    515         @Override
    516         public void writeToParcel(Parcel dest, int flags) {
    517             super.writeToParcel(dest, flags);
    518             dest.writeByte((byte) (mStereo ? 1 : 0));
    519             dest.writeByte((byte) (mRds ? 1 : 0));
    520             dest.writeByte((byte) (mTa ? 1 : 0));
    521             dest.writeByte((byte) (mAf ? 1 : 0));
    522         }
    523 
    524         @Override
    525         public int describeContents() {
    526             return 0;
    527         }
    528 
    529         @Override
    530         public String toString() {
    531             return "FmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo
    532                     + ", mRds=" + mRds + ", mTa=" + mTa + ", mAf=" + mAf + "]";
    533         }
    534 
    535         @Override
    536         public int hashCode() {
    537             final int prime = 31;
    538             int result = super.hashCode();
    539             result = prime * result + (mStereo ? 1 : 0);
    540             result = prime * result + (mRds ? 1 : 0);
    541             result = prime * result + (mTa ? 1 : 0);
    542             result = prime * result + (mAf ? 1 : 0);
    543             return result;
    544         }
    545 
    546         @Override
    547         public boolean equals(Object obj) {
    548             if (this == obj)
    549                 return true;
    550             if (!super.equals(obj))
    551                 return false;
    552             if (!(obj instanceof FmBandDescriptor))
    553                 return false;
    554             FmBandDescriptor other = (FmBandDescriptor) obj;
    555             if (mStereo != other.isStereoSupported())
    556                 return false;
    557             if (mRds != other.isRdsSupported())
    558                 return false;
    559             if (mTa != other.isTaSupported())
    560                 return false;
    561             if (mAf != other.isAfSupported())
    562                 return false;
    563             return true;
    564         }
    565     }
    566 
    567     /** AM band descriptor.
    568      * @see #BAND_AM */
    569     public static class AmBandDescriptor extends BandDescriptor {
    570 
    571         private final boolean mStereo;
    572 
    573         AmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing,
    574                 boolean stereo) {
    575             super(region, type, lowerLimit, upperLimit, spacing);
    576             mStereo = stereo;
    577         }
    578 
    579         /** Stereo is supported
    580          *  @return {@code true} if stereo is supported, {@code false} otherwise.
    581          */
    582         public boolean isStereoSupported() {
    583             return mStereo;
    584         }
    585 
    586         private AmBandDescriptor(Parcel in) {
    587             super(in);
    588             mStereo = in.readByte() == 1;
    589         }
    590 
    591         public static final Parcelable.Creator<AmBandDescriptor> CREATOR
    592                 = new Parcelable.Creator<AmBandDescriptor>() {
    593             public AmBandDescriptor createFromParcel(Parcel in) {
    594                 return new AmBandDescriptor(in);
    595             }
    596 
    597             public AmBandDescriptor[] newArray(int size) {
    598                 return new AmBandDescriptor[size];
    599             }
    600         };
    601 
    602         @Override
    603         public void writeToParcel(Parcel dest, int flags) {
    604             super.writeToParcel(dest, flags);
    605             dest.writeByte((byte) (mStereo ? 1 : 0));
    606         }
    607 
    608         @Override
    609         public int describeContents() {
    610             return 0;
    611         }
    612 
    613         @Override
    614         public String toString() {
    615             return "AmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo + "]";
    616         }
    617 
    618         @Override
    619         public int hashCode() {
    620             final int prime = 31;
    621             int result = super.hashCode();
    622             result = prime * result + (mStereo ? 1 : 0);
    623             return result;
    624         }
    625 
    626         @Override
    627         public boolean equals(Object obj) {
    628             if (this == obj)
    629                 return true;
    630             if (!super.equals(obj))
    631                 return false;
    632             if (!(obj instanceof AmBandDescriptor))
    633                 return false;
    634             AmBandDescriptor other = (AmBandDescriptor) obj;
    635             if (mStereo != other.isStereoSupported())
    636                 return false;
    637             return true;
    638         }
    639     }
    640 
    641 
    642     /** Radio band configuration. */
    643     public static class BandConfig implements Parcelable {
    644 
    645         final BandDescriptor mDescriptor;
    646 
    647         BandConfig(BandDescriptor descriptor) {
    648             mDescriptor = descriptor;
    649         }
    650 
    651         BandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing) {
    652             mDescriptor = new BandDescriptor(region, type, lowerLimit, upperLimit, spacing);
    653         }
    654 
    655         private BandConfig(Parcel in) {
    656             mDescriptor = new BandDescriptor(in);
    657         }
    658 
    659         BandDescriptor getDescriptor() {
    660             return mDescriptor;
    661         }
    662 
    663         /** Region this band applies to. E.g. {@link #REGION_ITU_1}
    664          *  @return the region associated with this band.
    665          */
    666         public int getRegion() {
    667             return mDescriptor.getRegion();
    668         }
    669         /** Band type, e.g {@link #BAND_FM}. Defines the subclass this descriptor can be cast to:
    670          * <ul>
    671          *  <li>{@link #BAND_FM} or {@link #BAND_FM_HD} cast to {@link FmBandDescriptor}, </li>
    672          *  <li>{@link #BAND_AM} cast to {@link AmBandDescriptor}, </li>
    673          * </ul>
    674          *  @return the band type.
    675          */
    676         public int getType() {
    677             return mDescriptor.getType();
    678         }
    679         /** Lower band limit expressed in units according to band type.
    680          * Currently all defined band types express channels as frequency in kHz
    681          *  @return the lower band limit.
    682          */
    683         public int getLowerLimit() {
    684             return mDescriptor.getLowerLimit();
    685         }
    686         /** Upper band limit expressed in units according to band type.
    687          * Currently all defined band types express channels as frequency in kHz
    688          *  @return the upper band limit.
    689          */
    690         public int getUpperLimit() {
    691             return mDescriptor.getUpperLimit();
    692         }
    693         /** Channel spacing in units according to band type.
    694          * Currently all defined band types express channels as frequency in kHz
    695          *  @return the channel spacing.
    696          */
    697         public int getSpacing() {
    698             return mDescriptor.getSpacing();
    699         }
    700 
    701 
    702         public static final Parcelable.Creator<BandConfig> CREATOR
    703                 = new Parcelable.Creator<BandConfig>() {
    704             public BandConfig createFromParcel(Parcel in) {
    705                 return new BandConfig(in);
    706             }
    707 
    708             public BandConfig[] newArray(int size) {
    709                 return new BandConfig[size];
    710             }
    711         };
    712 
    713         @Override
    714         public void writeToParcel(Parcel dest, int flags) {
    715             mDescriptor.writeToParcel(dest, flags);
    716         }
    717 
    718         @Override
    719         public int describeContents() {
    720             return 0;
    721         }
    722 
    723         @Override
    724         public String toString() {
    725             return "BandConfig [ " + mDescriptor.toString() + "]";
    726         }
    727 
    728         @Override
    729         public int hashCode() {
    730             final int prime = 31;
    731             int result = 1;
    732             result = prime * result + mDescriptor.hashCode();
    733             return result;
    734         }
    735 
    736         @Override
    737         public boolean equals(Object obj) {
    738             if (this == obj)
    739                 return true;
    740             if (!(obj instanceof BandConfig))
    741                 return false;
    742             BandConfig other = (BandConfig) obj;
    743             if (mDescriptor != other.getDescriptor())
    744                 return false;
    745             return true;
    746         }
    747     }
    748 
    749     /** FM band configuration.
    750      * @see #BAND_FM
    751      * @see #BAND_FM_HD */
    752     public static class FmBandConfig extends BandConfig {
    753         private final boolean mStereo;
    754         private final boolean mRds;
    755         private final boolean mTa;
    756         private final boolean mAf;
    757 
    758         FmBandConfig(FmBandDescriptor descriptor) {
    759             super((BandDescriptor)descriptor);
    760             mStereo = descriptor.isStereoSupported();
    761             mRds = descriptor.isRdsSupported();
    762             mTa = descriptor.isTaSupported();
    763             mAf = descriptor.isAfSupported();
    764         }
    765 
    766         FmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing,
    767                 boolean stereo, boolean rds, boolean ta, boolean af) {
    768             super(region, type, lowerLimit, upperLimit, spacing);
    769             mStereo = stereo;
    770             mRds = rds;
    771             mTa = ta;
    772             mAf = af;
    773         }
    774 
    775         /** Get stereo enable state
    776          * @return the enable state.
    777          */
    778         public boolean getStereo() {
    779             return mStereo;
    780         }
    781 
    782         /** Get RDS or RBDS(if region is ITU2) enable state
    783          * @return the enable state.
    784          */
    785         public boolean getRds() {
    786             return mRds;
    787         }
    788 
    789         /** Get Traffic announcement enable state
    790          * @return the enable state.
    791          */
    792         public boolean getTa() {
    793             return mTa;
    794         }
    795 
    796         /** Get Alternate Frequency Switching enable state
    797          * @return the enable state.
    798          */
    799         public boolean getAf() {
    800             return mAf;
    801         }
    802 
    803         private FmBandConfig(Parcel in) {
    804             super(in);
    805             mStereo = in.readByte() == 1;
    806             mRds = in.readByte() == 1;
    807             mTa = in.readByte() == 1;
    808             mAf = in.readByte() == 1;
    809         }
    810 
    811         public static final Parcelable.Creator<FmBandConfig> CREATOR
    812                 = new Parcelable.Creator<FmBandConfig>() {
    813             public FmBandConfig createFromParcel(Parcel in) {
    814                 return new FmBandConfig(in);
    815             }
    816 
    817             public FmBandConfig[] newArray(int size) {
    818                 return new FmBandConfig[size];
    819             }
    820         };
    821 
    822         @Override
    823         public void writeToParcel(Parcel dest, int flags) {
    824             super.writeToParcel(dest, flags);
    825             dest.writeByte((byte) (mStereo ? 1 : 0));
    826             dest.writeByte((byte) (mRds ? 1 : 0));
    827             dest.writeByte((byte) (mTa ? 1 : 0));
    828             dest.writeByte((byte) (mAf ? 1 : 0));
    829         }
    830 
    831         @Override
    832         public int describeContents() {
    833             return 0;
    834         }
    835 
    836         @Override
    837         public String toString() {
    838             return "FmBandConfig [" + super.toString()
    839                     + ", mStereo=" + mStereo + ", mRds=" + mRds + ", mTa=" + mTa
    840                     + ", mAf=" + mAf + "]";
    841         }
    842 
    843         @Override
    844         public int hashCode() {
    845             final int prime = 31;
    846             int result = super.hashCode();
    847             result = prime * result + (mStereo ? 1 : 0);
    848             result = prime * result + (mRds ? 1 : 0);
    849             result = prime * result + (mTa ? 1 : 0);
    850             result = prime * result + (mAf ? 1 : 0);
    851             return result;
    852         }
    853 
    854         @Override
    855         public boolean equals(Object obj) {
    856             if (this == obj)
    857                 return true;
    858             if (!super.equals(obj))
    859                 return false;
    860             if (!(obj instanceof FmBandConfig))
    861                 return false;
    862             FmBandConfig other = (FmBandConfig) obj;
    863             if (mStereo != other.mStereo)
    864                 return false;
    865             if (mRds != other.mRds)
    866                 return false;
    867             if (mTa != other.mTa)
    868                 return false;
    869             if (mAf != other.mAf)
    870                 return false;
    871             return true;
    872         }
    873 
    874         /**
    875          * Builder class for {@link FmBandConfig} objects.
    876          */
    877         public static class Builder {
    878             private final BandDescriptor mDescriptor;
    879             private boolean mStereo;
    880             private boolean mRds;
    881             private boolean mTa;
    882             private boolean mAf;
    883 
    884             /**
    885              * Constructs a new Builder with the defaults from an {@link FmBandDescriptor} .
    886              * @param descriptor the FmBandDescriptor defaults are read from .
    887              */
    888             public Builder(FmBandDescriptor descriptor) {
    889                 mDescriptor = new BandDescriptor(descriptor.getRegion(), descriptor.getType(),
    890                         descriptor.getLowerLimit(), descriptor.getUpperLimit(),
    891                         descriptor.getSpacing());
    892                 mStereo = descriptor.isStereoSupported();
    893                 mRds = descriptor.isRdsSupported();
    894                 mTa = descriptor.isTaSupported();
    895                 mAf = descriptor.isAfSupported();
    896             }
    897 
    898             /**
    899              * Constructs a new Builder from a given {@link FmBandConfig}
    900              * @param config the FmBandConfig object whose data will be reused in the new Builder.
    901              */
    902             public Builder(FmBandConfig config) {
    903                 mDescriptor = new BandDescriptor(config.getRegion(), config.getType(),
    904                         config.getLowerLimit(), config.getUpperLimit(), config.getSpacing());
    905                 mStereo = config.getStereo();
    906                 mRds = config.getRds();
    907                 mTa = config.getTa();
    908                 mAf = config.getAf();
    909             }
    910 
    911             /**
    912              * Combines all of the parameters that have been set and return a new
    913              * {@link FmBandConfig} object.
    914              * @return a new {@link FmBandConfig} object
    915              */
    916             public FmBandConfig build() {
    917                 FmBandConfig config = new FmBandConfig(mDescriptor.getRegion(),
    918                         mDescriptor.getType(), mDescriptor.getLowerLimit(),
    919                         mDescriptor.getUpperLimit(), mDescriptor.getSpacing(),
    920                         mStereo, mRds, mTa, mAf);
    921                 return config;
    922             }
    923 
    924             /** Set stereo enable state
    925              * @param state The new enable state.
    926              * @return the same Builder instance.
    927              */
    928             public Builder setStereo(boolean state) {
    929                 mStereo = state;
    930                 return this;
    931             }
    932 
    933             /** Set RDS or RBDS(if region is ITU2) enable state
    934              * @param state The new enable state.
    935              * @return the same Builder instance.
    936              */
    937             public Builder setRds(boolean state) {
    938                 mRds = state;
    939                 return this;
    940             }
    941 
    942             /** Set Traffic announcement enable state
    943              * @param state The new enable state.
    944              * @return the same Builder instance.
    945              */
    946             public Builder setTa(boolean state) {
    947                 mTa = state;
    948                 return this;
    949             }
    950 
    951             /** Set Alternate Frequency Switching enable state
    952              * @param state The new enable state.
    953              * @return the same Builder instance.
    954              */
    955             public Builder setAf(boolean state) {
    956                 mAf = state;
    957                 return this;
    958             }
    959         };
    960     }
    961 
    962     /** AM band configuration.
    963      * @see #BAND_AM */
    964     public static class AmBandConfig extends BandConfig {
    965         private final boolean mStereo;
    966 
    967         AmBandConfig(AmBandDescriptor descriptor) {
    968             super((BandDescriptor)descriptor);
    969             mStereo = descriptor.isStereoSupported();
    970         }
    971 
    972         AmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing,
    973                 boolean stereo) {
    974             super(region, type, lowerLimit, upperLimit, spacing);
    975             mStereo = stereo;
    976         }
    977 
    978         /** Get stereo enable state
    979          * @return the enable state.
    980          */
    981         public boolean getStereo() {
    982             return mStereo;
    983         }
    984 
    985         private AmBandConfig(Parcel in) {
    986             super(in);
    987             mStereo = in.readByte() == 1;
    988         }
    989 
    990         public static final Parcelable.Creator<AmBandConfig> CREATOR
    991                 = new Parcelable.Creator<AmBandConfig>() {
    992             public AmBandConfig createFromParcel(Parcel in) {
    993                 return new AmBandConfig(in);
    994             }
    995 
    996             public AmBandConfig[] newArray(int size) {
    997                 return new AmBandConfig[size];
    998             }
    999         };
   1000 
   1001         @Override
   1002         public void writeToParcel(Parcel dest, int flags) {
   1003             super.writeToParcel(dest, flags);
   1004             dest.writeByte((byte) (mStereo ? 1 : 0));
   1005         }
   1006 
   1007         @Override
   1008         public int describeContents() {
   1009             return 0;
   1010         }
   1011 
   1012         @Override
   1013         public String toString() {
   1014             return "AmBandConfig [" + super.toString()
   1015                     + ", mStereo=" + mStereo + "]";
   1016         }
   1017 
   1018         @Override
   1019         public int hashCode() {
   1020             final int prime = 31;
   1021             int result = super.hashCode();
   1022             result = prime * result + (mStereo ? 1 : 0);
   1023             return result;
   1024         }
   1025 
   1026         @Override
   1027         public boolean equals(Object obj) {
   1028             if (this == obj)
   1029                 return true;
   1030             if (!super.equals(obj))
   1031                 return false;
   1032             if (!(obj instanceof AmBandConfig))
   1033                 return false;
   1034             AmBandConfig other = (AmBandConfig) obj;
   1035             if (mStereo != other.getStereo())
   1036                 return false;
   1037             return true;
   1038         }
   1039 
   1040         /**
   1041          * Builder class for {@link AmBandConfig} objects.
   1042          */
   1043         public static class Builder {
   1044             private final BandDescriptor mDescriptor;
   1045             private boolean mStereo;
   1046 
   1047             /**
   1048              * Constructs a new Builder with the defaults from an {@link AmBandDescriptor} .
   1049              * @param descriptor the FmBandDescriptor defaults are read from .
   1050              */
   1051             public Builder(AmBandDescriptor descriptor) {
   1052                 mDescriptor = new BandDescriptor(descriptor.getRegion(), descriptor.getType(),
   1053                         descriptor.getLowerLimit(), descriptor.getUpperLimit(),
   1054                         descriptor.getSpacing());
   1055                 mStereo = descriptor.isStereoSupported();
   1056             }
   1057 
   1058             /**
   1059              * Constructs a new Builder from a given {@link AmBandConfig}
   1060              * @param config the FmBandConfig object whose data will be reused in the new Builder.
   1061              */
   1062             public Builder(AmBandConfig config) {
   1063                 mDescriptor = new BandDescriptor(config.getRegion(), config.getType(),
   1064                         config.getLowerLimit(), config.getUpperLimit(), config.getSpacing());
   1065                 mStereo = config.getStereo();
   1066             }
   1067 
   1068             /**
   1069              * Combines all of the parameters that have been set and return a new
   1070              * {@link AmBandConfig} object.
   1071              * @return a new {@link AmBandConfig} object
   1072              */
   1073             public AmBandConfig build() {
   1074                 AmBandConfig config = new AmBandConfig(mDescriptor.getRegion(),
   1075                         mDescriptor.getType(), mDescriptor.getLowerLimit(),
   1076                         mDescriptor.getUpperLimit(), mDescriptor.getSpacing(),
   1077                         mStereo);
   1078                 return config;
   1079             }
   1080 
   1081             /** Set stereo enable state
   1082              * @param state The new enable state.
   1083              * @return the same Builder instance.
   1084              */
   1085             public Builder setStereo(boolean state) {
   1086                 mStereo = state;
   1087                 return this;
   1088             }
   1089         };
   1090     }
   1091 
   1092     /** Radio program information returned by
   1093      * {@link RadioTuner#getProgramInformation(RadioManager.ProgramInfo[])} */
   1094     public static class ProgramInfo implements Parcelable {
   1095 
   1096         private final int mChannel;
   1097         private final int mSubChannel;
   1098         private final boolean mTuned;
   1099         private final boolean mStereo;
   1100         private final boolean mDigital;
   1101         private final int mSignalStrength;
   1102         private final RadioMetadata mMetadata;
   1103 
   1104         ProgramInfo(int channel, int subChannel, boolean tuned, boolean stereo,
   1105                 boolean digital, int signalStrength, RadioMetadata metadata) {
   1106             mChannel = channel;
   1107             mSubChannel = subChannel;
   1108             mTuned = tuned;
   1109             mStereo = stereo;
   1110             mDigital = digital;
   1111             mSignalStrength = signalStrength;
   1112             mMetadata = metadata;
   1113         }
   1114 
   1115         /** Main channel expressed in units according to band type.
   1116          * Currently all defined band types express channels as frequency in kHz
   1117          * @return the program channel
   1118          */
   1119         public int getChannel() {
   1120             return mChannel;
   1121         }
   1122         /** Sub channel ID. E.g 1 for HD radio HD1
   1123          * @return the program sub channel
   1124          */
   1125         public int getSubChannel() {
   1126             return mSubChannel;
   1127         }
   1128         /** {@code true} if the tuner is currently tuned on a valid station
   1129          * @return {@code true} if currently tuned, {@code false} otherwise.
   1130          */
   1131         public boolean isTuned() {
   1132             return mTuned;
   1133         }
   1134         /** {@code true} if the received program is stereo
   1135          * @return {@code true} if stereo, {@code false} otherwise.
   1136          */
   1137         public boolean isStereo() {
   1138             return mStereo;
   1139         }
   1140         /** {@code true} if the received program is digital (e.g HD radio)
   1141          * @return {@code true} if digital, {@code false} otherwise.
   1142          */
   1143         public boolean isDigital() {
   1144             return mDigital;
   1145         }
   1146         /** Signal strength indicator from 0 (no signal) to 100 (excellent)
   1147          * @return the signal strength indication.
   1148          */
   1149         public int getSignalStrength() {
   1150             return mSignalStrength;
   1151         }
   1152         /** Metadata currently received from this station.
   1153          * null if no metadata have been received
   1154          * @return current meta data received from this program.
   1155          */
   1156         public RadioMetadata getMetadata() {
   1157             return mMetadata;
   1158         }
   1159 
   1160         private ProgramInfo(Parcel in) {
   1161             mChannel = in.readInt();
   1162             mSubChannel = in.readInt();
   1163             mTuned = in.readByte() == 1;
   1164             mStereo = in.readByte() == 1;
   1165             mDigital = in.readByte() == 1;
   1166             mSignalStrength = in.readInt();
   1167             if (in.readByte() == 1) {
   1168                 mMetadata = RadioMetadata.CREATOR.createFromParcel(in);
   1169             } else {
   1170                 mMetadata = null;
   1171             }
   1172         }
   1173 
   1174         public static final Parcelable.Creator<ProgramInfo> CREATOR
   1175                 = new Parcelable.Creator<ProgramInfo>() {
   1176             public ProgramInfo createFromParcel(Parcel in) {
   1177                 return new ProgramInfo(in);
   1178             }
   1179 
   1180             public ProgramInfo[] newArray(int size) {
   1181                 return new ProgramInfo[size];
   1182             }
   1183         };
   1184 
   1185         @Override
   1186         public void writeToParcel(Parcel dest, int flags) {
   1187             dest.writeInt(mChannel);
   1188             dest.writeInt(mSubChannel);
   1189             dest.writeByte((byte)(mTuned ? 1 : 0));
   1190             dest.writeByte((byte)(mStereo ? 1 : 0));
   1191             dest.writeByte((byte)(mDigital ? 1 : 0));
   1192             dest.writeInt(mSignalStrength);
   1193             if (mMetadata == null) {
   1194                 dest.writeByte((byte)0);
   1195             } else {
   1196                 dest.writeByte((byte)1);
   1197                 mMetadata.writeToParcel(dest, flags);
   1198             }
   1199         }
   1200 
   1201         @Override
   1202         public int describeContents() {
   1203             return 0;
   1204         }
   1205 
   1206         @Override
   1207         public String toString() {
   1208             return "ProgramInfo [mChannel=" + mChannel + ", mSubChannel=" + mSubChannel
   1209                     + ", mTuned=" + mTuned + ", mStereo=" + mStereo + ", mDigital=" + mDigital
   1210                     + ", mSignalStrength=" + mSignalStrength
   1211                     + ((mMetadata == null) ? "" : (", mMetadata=" + mMetadata.toString()))
   1212                     + "]";
   1213         }
   1214 
   1215         @Override
   1216         public int hashCode() {
   1217             final int prime = 31;
   1218             int result = 1;
   1219             result = prime * result + mChannel;
   1220             result = prime * result + mSubChannel;
   1221             result = prime * result + (mTuned ? 1 : 0);
   1222             result = prime * result + (mStereo ? 1 : 0);
   1223             result = prime * result + (mDigital ? 1 : 0);
   1224             result = prime * result + mSignalStrength;
   1225             result = prime * result + ((mMetadata == null) ? 0 : mMetadata.hashCode());
   1226             return result;
   1227         }
   1228 
   1229         @Override
   1230         public boolean equals(Object obj) {
   1231             if (this == obj)
   1232                 return true;
   1233             if (!(obj instanceof ProgramInfo))
   1234                 return false;
   1235             ProgramInfo other = (ProgramInfo) obj;
   1236             if (mChannel != other.getChannel())
   1237                 return false;
   1238             if (mSubChannel != other.getSubChannel())
   1239                 return false;
   1240             if (mTuned != other.isTuned())
   1241                 return false;
   1242             if (mStereo != other.isStereo())
   1243                 return false;
   1244             if (mDigital != other.isDigital())
   1245                 return false;
   1246             if (mSignalStrength != other.getSignalStrength())
   1247                 return false;
   1248             if (mMetadata == null) {
   1249                 if (other.getMetadata() != null)
   1250                     return false;
   1251             } else if (!mMetadata.equals(other.getMetadata()))
   1252                 return false;
   1253             return true;
   1254         }
   1255     }
   1256 
   1257 
   1258     /**
   1259      * Returns a list of descriptors for all broadcast radio modules present on the device.
   1260      * @param modules An List of {@link ModuleProperties} where the list will be returned.
   1261      * @return
   1262      * <ul>
   1263      *  <li>{@link #STATUS_OK} in case of success, </li>
   1264      *  <li>{@link #STATUS_ERROR} in case of unspecified error, </li>
   1265      *  <li>{@link #STATUS_NO_INIT} if the native service cannot be reached, </li>
   1266      *  <li>{@link #STATUS_BAD_VALUE} if modules is null, </li>
   1267      *  <li>{@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails, </li>
   1268      * </ul>
   1269      */
   1270     public native int listModules(List <ModuleProperties> modules);
   1271 
   1272     /**
   1273      * Open an interface to control a tuner on a given broadcast radio module.
   1274      * Optionally selects and applies the configuration passed as "config" argument.
   1275      * @param moduleId radio module identifier {@link ModuleProperties#getId()}. Mandatory.
   1276      * @param config desired band and configuration to apply when enabling the hardware module.
   1277      * optional, can be null.
   1278      * @param withAudio {@code true} to request a tuner with an audio source.
   1279      * This tuner is intended for live listening or recording or a radio program.
   1280      * If {@code false}, the tuner can only be used to retrieve program informations.
   1281      * @param callback {@link RadioTuner.Callback} interface. Mandatory.
   1282      * @param handler the Handler on which the callbacks will be received.
   1283      * Can be null if default handler is OK.
   1284      * @return a valid {@link RadioTuner} interface in case of success or null in case of error.
   1285      */
   1286     public RadioTuner openTuner(int moduleId, BandConfig config, boolean withAudio,
   1287             RadioTuner.Callback callback, Handler handler) {
   1288         if (callback == null) {
   1289             return null;
   1290         }
   1291         RadioModule module = new RadioModule(moduleId, config, withAudio, callback, handler);
   1292         if (module != null) {
   1293             if (!module.initCheck()) {
   1294                 module = null;
   1295             }
   1296         }
   1297         return (RadioTuner)module;
   1298     }
   1299 
   1300     private final Context mContext;
   1301 
   1302     /**
   1303      * @hide
   1304      */
   1305     public RadioManager(Context context) {
   1306         mContext = context;
   1307     }
   1308 }
   1309