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         private final boolean mEa;
    461 
    462         FmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing,
    463                 boolean stereo, boolean rds, boolean ta, boolean af, boolean ea) {
    464             super(region, type, lowerLimit, upperLimit, spacing);
    465             mStereo = stereo;
    466             mRds = rds;
    467             mTa = ta;
    468             mAf = af;
    469             mEa = ea;
    470         }
    471 
    472         /** Stereo is supported
    473          * @return {@code true} if stereo is supported, {@code false} otherwise.
    474          */
    475         public boolean isStereoSupported() {
    476             return mStereo;
    477         }
    478         /** RDS or RBDS(if region is ITU2) is supported
    479          * @return {@code true} if RDS or RBDS is supported, {@code false} otherwise.
    480          */
    481         public boolean isRdsSupported() {
    482             return mRds;
    483         }
    484         /** Traffic announcement is supported
    485          * @return {@code true} if TA is supported, {@code false} otherwise.
    486          */
    487         public boolean isTaSupported() {
    488             return mTa;
    489         }
    490         /** Alternate Frequency Switching is supported
    491          * @return {@code true} if AF switching is supported, {@code false} otherwise.
    492          */
    493         public boolean isAfSupported() {
    494             return mAf;
    495         }
    496 
    497         /** Emergency Announcement is supported
    498          * @return {@code true} if Emergency annoucement is supported, {@code false} otherwise.
    499          */
    500         public boolean isEaSupported() {
    501             return mEa;
    502         }
    503 
    504         /* Parcelable implementation */
    505         private FmBandDescriptor(Parcel in) {
    506             super(in);
    507             mStereo = in.readByte() == 1;
    508             mRds = in.readByte() == 1;
    509             mTa = in.readByte() == 1;
    510             mAf = in.readByte() == 1;
    511             mEa = in.readByte() == 1;
    512         }
    513 
    514         public static final Parcelable.Creator<FmBandDescriptor> CREATOR
    515                 = new Parcelable.Creator<FmBandDescriptor>() {
    516             public FmBandDescriptor createFromParcel(Parcel in) {
    517                 return new FmBandDescriptor(in);
    518             }
    519 
    520             public FmBandDescriptor[] newArray(int size) {
    521                 return new FmBandDescriptor[size];
    522             }
    523         };
    524 
    525         @Override
    526         public void writeToParcel(Parcel dest, int flags) {
    527             super.writeToParcel(dest, flags);
    528             dest.writeByte((byte) (mStereo ? 1 : 0));
    529             dest.writeByte((byte) (mRds ? 1 : 0));
    530             dest.writeByte((byte) (mTa ? 1 : 0));
    531             dest.writeByte((byte) (mAf ? 1 : 0));
    532             dest.writeByte((byte) (mEa ? 1 : 0));
    533         }
    534 
    535         @Override
    536         public int describeContents() {
    537             return 0;
    538         }
    539 
    540         @Override
    541         public String toString() {
    542             return "FmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo
    543                     + ", mRds=" + mRds + ", mTa=" + mTa + ", mAf=" + mAf +
    544                     ", mEa =" + mEa + "]";
    545         }
    546 
    547         @Override
    548         public int hashCode() {
    549             final int prime = 31;
    550             int result = super.hashCode();
    551             result = prime * result + (mStereo ? 1 : 0);
    552             result = prime * result + (mRds ? 1 : 0);
    553             result = prime * result + (mTa ? 1 : 0);
    554             result = prime * result + (mAf ? 1 : 0);
    555             result = prime * result + (mEa ? 1 : 0);
    556             return result;
    557         }
    558 
    559         @Override
    560         public boolean equals(Object obj) {
    561             if (this == obj)
    562                 return true;
    563             if (!super.equals(obj))
    564                 return false;
    565             if (!(obj instanceof FmBandDescriptor))
    566                 return false;
    567             FmBandDescriptor other = (FmBandDescriptor) obj;
    568             if (mStereo != other.isStereoSupported())
    569                 return false;
    570             if (mRds != other.isRdsSupported())
    571                 return false;
    572             if (mTa != other.isTaSupported())
    573                 return false;
    574             if (mAf != other.isAfSupported())
    575                 return false;
    576             if (mEa != other.isEaSupported())
    577                 return false;
    578             return true;
    579         }
    580     }
    581 
    582     /** AM band descriptor.
    583      * @see #BAND_AM */
    584     public static class AmBandDescriptor extends BandDescriptor {
    585 
    586         private final boolean mStereo;
    587 
    588         AmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing,
    589                 boolean stereo) {
    590             super(region, type, lowerLimit, upperLimit, spacing);
    591             mStereo = stereo;
    592         }
    593 
    594         /** Stereo is supported
    595          *  @return {@code true} if stereo is supported, {@code false} otherwise.
    596          */
    597         public boolean isStereoSupported() {
    598             return mStereo;
    599         }
    600 
    601         private AmBandDescriptor(Parcel in) {
    602             super(in);
    603             mStereo = in.readByte() == 1;
    604         }
    605 
    606         public static final Parcelable.Creator<AmBandDescriptor> CREATOR
    607                 = new Parcelable.Creator<AmBandDescriptor>() {
    608             public AmBandDescriptor createFromParcel(Parcel in) {
    609                 return new AmBandDescriptor(in);
    610             }
    611 
    612             public AmBandDescriptor[] newArray(int size) {
    613                 return new AmBandDescriptor[size];
    614             }
    615         };
    616 
    617         @Override
    618         public void writeToParcel(Parcel dest, int flags) {
    619             super.writeToParcel(dest, flags);
    620             dest.writeByte((byte) (mStereo ? 1 : 0));
    621         }
    622 
    623         @Override
    624         public int describeContents() {
    625             return 0;
    626         }
    627 
    628         @Override
    629         public String toString() {
    630             return "AmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo + "]";
    631         }
    632 
    633         @Override
    634         public int hashCode() {
    635             final int prime = 31;
    636             int result = super.hashCode();
    637             result = prime * result + (mStereo ? 1 : 0);
    638             return result;
    639         }
    640 
    641         @Override
    642         public boolean equals(Object obj) {
    643             if (this == obj)
    644                 return true;
    645             if (!super.equals(obj))
    646                 return false;
    647             if (!(obj instanceof AmBandDescriptor))
    648                 return false;
    649             AmBandDescriptor other = (AmBandDescriptor) obj;
    650             if (mStereo != other.isStereoSupported())
    651                 return false;
    652             return true;
    653         }
    654     }
    655 
    656 
    657     /** Radio band configuration. */
    658     public static class BandConfig implements Parcelable {
    659 
    660         final BandDescriptor mDescriptor;
    661 
    662         BandConfig(BandDescriptor descriptor) {
    663             mDescriptor = descriptor;
    664         }
    665 
    666         BandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing) {
    667             mDescriptor = new BandDescriptor(region, type, lowerLimit, upperLimit, spacing);
    668         }
    669 
    670         private BandConfig(Parcel in) {
    671             mDescriptor = new BandDescriptor(in);
    672         }
    673 
    674         BandDescriptor getDescriptor() {
    675             return mDescriptor;
    676         }
    677 
    678         /** Region this band applies to. E.g. {@link #REGION_ITU_1}
    679          *  @return the region associated with this band.
    680          */
    681         public int getRegion() {
    682             return mDescriptor.getRegion();
    683         }
    684         /** Band type, e.g {@link #BAND_FM}. Defines the subclass this descriptor can be cast to:
    685          * <ul>
    686          *  <li>{@link #BAND_FM} or {@link #BAND_FM_HD} cast to {@link FmBandDescriptor}, </li>
    687          *  <li>{@link #BAND_AM} cast to {@link AmBandDescriptor}, </li>
    688          * </ul>
    689          *  @return the band type.
    690          */
    691         public int getType() {
    692             return mDescriptor.getType();
    693         }
    694         /** Lower band limit expressed in units according to band type.
    695          * Currently all defined band types express channels as frequency in kHz
    696          *  @return the lower band limit.
    697          */
    698         public int getLowerLimit() {
    699             return mDescriptor.getLowerLimit();
    700         }
    701         /** Upper band limit expressed in units according to band type.
    702          * Currently all defined band types express channels as frequency in kHz
    703          *  @return the upper band limit.
    704          */
    705         public int getUpperLimit() {
    706             return mDescriptor.getUpperLimit();
    707         }
    708         /** Channel spacing in units according to band type.
    709          * Currently all defined band types express channels as frequency in kHz
    710          *  @return the channel spacing.
    711          */
    712         public int getSpacing() {
    713             return mDescriptor.getSpacing();
    714         }
    715 
    716 
    717         public static final Parcelable.Creator<BandConfig> CREATOR
    718                 = new Parcelable.Creator<BandConfig>() {
    719             public BandConfig createFromParcel(Parcel in) {
    720                 return new BandConfig(in);
    721             }
    722 
    723             public BandConfig[] newArray(int size) {
    724                 return new BandConfig[size];
    725             }
    726         };
    727 
    728         @Override
    729         public void writeToParcel(Parcel dest, int flags) {
    730             mDescriptor.writeToParcel(dest, flags);
    731         }
    732 
    733         @Override
    734         public int describeContents() {
    735             return 0;
    736         }
    737 
    738         @Override
    739         public String toString() {
    740             return "BandConfig [ " + mDescriptor.toString() + "]";
    741         }
    742 
    743         @Override
    744         public int hashCode() {
    745             final int prime = 31;
    746             int result = 1;
    747             result = prime * result + mDescriptor.hashCode();
    748             return result;
    749         }
    750 
    751         @Override
    752         public boolean equals(Object obj) {
    753             if (this == obj)
    754                 return true;
    755             if (!(obj instanceof BandConfig))
    756                 return false;
    757             BandConfig other = (BandConfig) obj;
    758             if (mDescriptor != other.getDescriptor())
    759                 return false;
    760             return true;
    761         }
    762     }
    763 
    764     /** FM band configuration.
    765      * @see #BAND_FM
    766      * @see #BAND_FM_HD */
    767     public static class FmBandConfig extends BandConfig {
    768         private final boolean mStereo;
    769         private final boolean mRds;
    770         private final boolean mTa;
    771         private final boolean mAf;
    772         private final boolean mEa;
    773 
    774         FmBandConfig(FmBandDescriptor descriptor) {
    775             super((BandDescriptor)descriptor);
    776             mStereo = descriptor.isStereoSupported();
    777             mRds = descriptor.isRdsSupported();
    778             mTa = descriptor.isTaSupported();
    779             mAf = descriptor.isAfSupported();
    780             mEa = descriptor.isEaSupported();
    781         }
    782 
    783         FmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing,
    784                 boolean stereo, boolean rds, boolean ta, boolean af, boolean ea) {
    785             super(region, type, lowerLimit, upperLimit, spacing);
    786             mStereo = stereo;
    787             mRds = rds;
    788             mTa = ta;
    789             mAf = af;
    790             mEa = ea;
    791         }
    792 
    793         /** Get stereo enable state
    794          * @return the enable state.
    795          */
    796         public boolean getStereo() {
    797             return mStereo;
    798         }
    799 
    800         /** Get RDS or RBDS(if region is ITU2) enable state
    801          * @return the enable state.
    802          */
    803         public boolean getRds() {
    804             return mRds;
    805         }
    806 
    807         /** Get Traffic announcement enable state
    808          * @return the enable state.
    809          */
    810         public boolean getTa() {
    811             return mTa;
    812         }
    813 
    814         /** Get Alternate Frequency Switching enable state
    815          * @return the enable state.
    816          */
    817         public boolean getAf() {
    818             return mAf;
    819         }
    820 
    821         /**
    822          * Get Emergency announcement enable state
    823          * @return the enable state.
    824          */
    825         public boolean getEa() {
    826             return mEa;
    827         }
    828 
    829         private FmBandConfig(Parcel in) {
    830             super(in);
    831             mStereo = in.readByte() == 1;
    832             mRds = in.readByte() == 1;
    833             mTa = in.readByte() == 1;
    834             mAf = in.readByte() == 1;
    835             mEa = in.readByte() == 1;
    836         }
    837 
    838         public static final Parcelable.Creator<FmBandConfig> CREATOR
    839                 = new Parcelable.Creator<FmBandConfig>() {
    840             public FmBandConfig createFromParcel(Parcel in) {
    841                 return new FmBandConfig(in);
    842             }
    843 
    844             public FmBandConfig[] newArray(int size) {
    845                 return new FmBandConfig[size];
    846             }
    847         };
    848 
    849         @Override
    850         public void writeToParcel(Parcel dest, int flags) {
    851             super.writeToParcel(dest, flags);
    852             dest.writeByte((byte) (mStereo ? 1 : 0));
    853             dest.writeByte((byte) (mRds ? 1 : 0));
    854             dest.writeByte((byte) (mTa ? 1 : 0));
    855             dest.writeByte((byte) (mAf ? 1 : 0));
    856             dest.writeByte((byte) (mEa ? 1 : 0));
    857         }
    858 
    859         @Override
    860         public int describeContents() {
    861             return 0;
    862         }
    863 
    864         @Override
    865         public String toString() {
    866             return "FmBandConfig [" + super.toString()
    867                     + ", mStereo=" + mStereo + ", mRds=" + mRds + ", mTa=" + mTa
    868                     + ", mAf=" + mAf + ", mEa =" + mEa + "]";
    869         }
    870 
    871         @Override
    872         public int hashCode() {
    873             final int prime = 31;
    874             int result = super.hashCode();
    875             result = prime * result + (mStereo ? 1 : 0);
    876             result = prime * result + (mRds ? 1 : 0);
    877             result = prime * result + (mTa ? 1 : 0);
    878             result = prime * result + (mAf ? 1 : 0);
    879             result = prime * result + (mEa ? 1 : 0);
    880             return result;
    881         }
    882 
    883         @Override
    884         public boolean equals(Object obj) {
    885             if (this == obj)
    886                 return true;
    887             if (!super.equals(obj))
    888                 return false;
    889             if (!(obj instanceof FmBandConfig))
    890                 return false;
    891             FmBandConfig other = (FmBandConfig) obj;
    892             if (mStereo != other.mStereo)
    893                 return false;
    894             if (mRds != other.mRds)
    895                 return false;
    896             if (mTa != other.mTa)
    897                 return false;
    898             if (mAf != other.mAf)
    899                 return false;
    900             if (mEa != other.mEa)
    901                 return false;
    902             return true;
    903         }
    904 
    905         /**
    906          * Builder class for {@link FmBandConfig} objects.
    907          */
    908         public static class Builder {
    909             private final BandDescriptor mDescriptor;
    910             private boolean mStereo;
    911             private boolean mRds;
    912             private boolean mTa;
    913             private boolean mAf;
    914             private boolean mEa;
    915 
    916             /**
    917              * Constructs a new Builder with the defaults from an {@link FmBandDescriptor} .
    918              * @param descriptor the FmBandDescriptor defaults are read from .
    919              */
    920             public Builder(FmBandDescriptor descriptor) {
    921                 mDescriptor = new BandDescriptor(descriptor.getRegion(), descriptor.getType(),
    922                         descriptor.getLowerLimit(), descriptor.getUpperLimit(),
    923                         descriptor.getSpacing());
    924                 mStereo = descriptor.isStereoSupported();
    925                 mRds = descriptor.isRdsSupported();
    926                 mTa = descriptor.isTaSupported();
    927                 mAf = descriptor.isAfSupported();
    928                 mEa = descriptor.isEaSupported();
    929             }
    930 
    931             /**
    932              * Constructs a new Builder from a given {@link FmBandConfig}
    933              * @param config the FmBandConfig object whose data will be reused in the new Builder.
    934              */
    935             public Builder(FmBandConfig config) {
    936                 mDescriptor = new BandDescriptor(config.getRegion(), config.getType(),
    937                         config.getLowerLimit(), config.getUpperLimit(), config.getSpacing());
    938                 mStereo = config.getStereo();
    939                 mRds = config.getRds();
    940                 mTa = config.getTa();
    941                 mAf = config.getAf();
    942                 mEa = config.getEa();
    943             }
    944 
    945             /**
    946              * Combines all of the parameters that have been set and return a new
    947              * {@link FmBandConfig} object.
    948              * @return a new {@link FmBandConfig} object
    949              */
    950             public FmBandConfig build() {
    951                 FmBandConfig config = new FmBandConfig(mDescriptor.getRegion(),
    952                         mDescriptor.getType(), mDescriptor.getLowerLimit(),
    953                         mDescriptor.getUpperLimit(), mDescriptor.getSpacing(),
    954                         mStereo, mRds, mTa, mAf, mEa);
    955                 return config;
    956             }
    957 
    958             /** Set stereo enable state
    959              * @param state The new enable state.
    960              * @return the same Builder instance.
    961              */
    962             public Builder setStereo(boolean state) {
    963                 mStereo = state;
    964                 return this;
    965             }
    966 
    967             /** Set RDS or RBDS(if region is ITU2) enable state
    968              * @param state The new enable state.
    969              * @return the same Builder instance.
    970              */
    971             public Builder setRds(boolean state) {
    972                 mRds = state;
    973                 return this;
    974             }
    975 
    976             /** Set Traffic announcement enable state
    977              * @param state The new enable state.
    978              * @return the same Builder instance.
    979              */
    980             public Builder setTa(boolean state) {
    981                 mTa = state;
    982                 return this;
    983             }
    984 
    985             /** Set Alternate Frequency Switching enable state
    986              * @param state The new enable state.
    987              * @return the same Builder instance.
    988              */
    989             public Builder setAf(boolean state) {
    990                 mAf = state;
    991                 return this;
    992             }
    993 
    994             /** Set Emergency Announcement enable state
    995              * @param state The new enable state.
    996              * @return the same Builder instance.
    997              */
    998             public Builder setEa(boolean state) {
    999                 mEa = state;
   1000                 return this;
   1001             }
   1002         };
   1003     }
   1004 
   1005     /** AM band configuration.
   1006      * @see #BAND_AM */
   1007     public static class AmBandConfig extends BandConfig {
   1008         private final boolean mStereo;
   1009 
   1010         AmBandConfig(AmBandDescriptor descriptor) {
   1011             super((BandDescriptor)descriptor);
   1012             mStereo = descriptor.isStereoSupported();
   1013         }
   1014 
   1015         AmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing,
   1016                 boolean stereo) {
   1017             super(region, type, lowerLimit, upperLimit, spacing);
   1018             mStereo = stereo;
   1019         }
   1020 
   1021         /** Get stereo enable state
   1022          * @return the enable state.
   1023          */
   1024         public boolean getStereo() {
   1025             return mStereo;
   1026         }
   1027 
   1028         private AmBandConfig(Parcel in) {
   1029             super(in);
   1030             mStereo = in.readByte() == 1;
   1031         }
   1032 
   1033         public static final Parcelable.Creator<AmBandConfig> CREATOR
   1034                 = new Parcelable.Creator<AmBandConfig>() {
   1035             public AmBandConfig createFromParcel(Parcel in) {
   1036                 return new AmBandConfig(in);
   1037             }
   1038 
   1039             public AmBandConfig[] newArray(int size) {
   1040                 return new AmBandConfig[size];
   1041             }
   1042         };
   1043 
   1044         @Override
   1045         public void writeToParcel(Parcel dest, int flags) {
   1046             super.writeToParcel(dest, flags);
   1047             dest.writeByte((byte) (mStereo ? 1 : 0));
   1048         }
   1049 
   1050         @Override
   1051         public int describeContents() {
   1052             return 0;
   1053         }
   1054 
   1055         @Override
   1056         public String toString() {
   1057             return "AmBandConfig [" + super.toString()
   1058                     + ", mStereo=" + mStereo + "]";
   1059         }
   1060 
   1061         @Override
   1062         public int hashCode() {
   1063             final int prime = 31;
   1064             int result = super.hashCode();
   1065             result = prime * result + (mStereo ? 1 : 0);
   1066             return result;
   1067         }
   1068 
   1069         @Override
   1070         public boolean equals(Object obj) {
   1071             if (this == obj)
   1072                 return true;
   1073             if (!super.equals(obj))
   1074                 return false;
   1075             if (!(obj instanceof AmBandConfig))
   1076                 return false;
   1077             AmBandConfig other = (AmBandConfig) obj;
   1078             if (mStereo != other.getStereo())
   1079                 return false;
   1080             return true;
   1081         }
   1082 
   1083         /**
   1084          * Builder class for {@link AmBandConfig} objects.
   1085          */
   1086         public static class Builder {
   1087             private final BandDescriptor mDescriptor;
   1088             private boolean mStereo;
   1089 
   1090             /**
   1091              * Constructs a new Builder with the defaults from an {@link AmBandDescriptor} .
   1092              * @param descriptor the FmBandDescriptor defaults are read from .
   1093              */
   1094             public Builder(AmBandDescriptor descriptor) {
   1095                 mDescriptor = new BandDescriptor(descriptor.getRegion(), descriptor.getType(),
   1096                         descriptor.getLowerLimit(), descriptor.getUpperLimit(),
   1097                         descriptor.getSpacing());
   1098                 mStereo = descriptor.isStereoSupported();
   1099             }
   1100 
   1101             /**
   1102              * Constructs a new Builder from a given {@link AmBandConfig}
   1103              * @param config the FmBandConfig object whose data will be reused in the new Builder.
   1104              */
   1105             public Builder(AmBandConfig config) {
   1106                 mDescriptor = new BandDescriptor(config.getRegion(), config.getType(),
   1107                         config.getLowerLimit(), config.getUpperLimit(), config.getSpacing());
   1108                 mStereo = config.getStereo();
   1109             }
   1110 
   1111             /**
   1112              * Combines all of the parameters that have been set and return a new
   1113              * {@link AmBandConfig} object.
   1114              * @return a new {@link AmBandConfig} object
   1115              */
   1116             public AmBandConfig build() {
   1117                 AmBandConfig config = new AmBandConfig(mDescriptor.getRegion(),
   1118                         mDescriptor.getType(), mDescriptor.getLowerLimit(),
   1119                         mDescriptor.getUpperLimit(), mDescriptor.getSpacing(),
   1120                         mStereo);
   1121                 return config;
   1122             }
   1123 
   1124             /** Set stereo enable state
   1125              * @param state The new enable state.
   1126              * @return the same Builder instance.
   1127              */
   1128             public Builder setStereo(boolean state) {
   1129                 mStereo = state;
   1130                 return this;
   1131             }
   1132         };
   1133     }
   1134 
   1135     /** Radio program information returned by
   1136      * {@link RadioTuner#getProgramInformation(RadioManager.ProgramInfo[])} */
   1137     public static class ProgramInfo implements Parcelable {
   1138 
   1139         private final int mChannel;
   1140         private final int mSubChannel;
   1141         private final boolean mTuned;
   1142         private final boolean mStereo;
   1143         private final boolean mDigital;
   1144         private final int mSignalStrength;
   1145         private final RadioMetadata mMetadata;
   1146 
   1147         ProgramInfo(int channel, int subChannel, boolean tuned, boolean stereo,
   1148                 boolean digital, int signalStrength, RadioMetadata metadata) {
   1149             mChannel = channel;
   1150             mSubChannel = subChannel;
   1151             mTuned = tuned;
   1152             mStereo = stereo;
   1153             mDigital = digital;
   1154             mSignalStrength = signalStrength;
   1155             mMetadata = metadata;
   1156         }
   1157 
   1158         /** Main channel expressed in units according to band type.
   1159          * Currently all defined band types express channels as frequency in kHz
   1160          * @return the program channel
   1161          */
   1162         public int getChannel() {
   1163             return mChannel;
   1164         }
   1165         /** Sub channel ID. E.g 1 for HD radio HD1
   1166          * @return the program sub channel
   1167          */
   1168         public int getSubChannel() {
   1169             return mSubChannel;
   1170         }
   1171         /** {@code true} if the tuner is currently tuned on a valid station
   1172          * @return {@code true} if currently tuned, {@code false} otherwise.
   1173          */
   1174         public boolean isTuned() {
   1175             return mTuned;
   1176         }
   1177         /** {@code true} if the received program is stereo
   1178          * @return {@code true} if stereo, {@code false} otherwise.
   1179          */
   1180         public boolean isStereo() {
   1181             return mStereo;
   1182         }
   1183         /** {@code true} if the received program is digital (e.g HD radio)
   1184          * @return {@code true} if digital, {@code false} otherwise.
   1185          */
   1186         public boolean isDigital() {
   1187             return mDigital;
   1188         }
   1189         /** Signal strength indicator from 0 (no signal) to 100 (excellent)
   1190          * @return the signal strength indication.
   1191          */
   1192         public int getSignalStrength() {
   1193             return mSignalStrength;
   1194         }
   1195         /** Metadata currently received from this station.
   1196          * null if no metadata have been received
   1197          * @return current meta data received from this program.
   1198          */
   1199         public RadioMetadata getMetadata() {
   1200             return mMetadata;
   1201         }
   1202 
   1203         private ProgramInfo(Parcel in) {
   1204             mChannel = in.readInt();
   1205             mSubChannel = in.readInt();
   1206             mTuned = in.readByte() == 1;
   1207             mStereo = in.readByte() == 1;
   1208             mDigital = in.readByte() == 1;
   1209             mSignalStrength = in.readInt();
   1210             if (in.readByte() == 1) {
   1211                 mMetadata = RadioMetadata.CREATOR.createFromParcel(in);
   1212             } else {
   1213                 mMetadata = null;
   1214             }
   1215         }
   1216 
   1217         public static final Parcelable.Creator<ProgramInfo> CREATOR
   1218                 = new Parcelable.Creator<ProgramInfo>() {
   1219             public ProgramInfo createFromParcel(Parcel in) {
   1220                 return new ProgramInfo(in);
   1221             }
   1222 
   1223             public ProgramInfo[] newArray(int size) {
   1224                 return new ProgramInfo[size];
   1225             }
   1226         };
   1227 
   1228         @Override
   1229         public void writeToParcel(Parcel dest, int flags) {
   1230             dest.writeInt(mChannel);
   1231             dest.writeInt(mSubChannel);
   1232             dest.writeByte((byte)(mTuned ? 1 : 0));
   1233             dest.writeByte((byte)(mStereo ? 1 : 0));
   1234             dest.writeByte((byte)(mDigital ? 1 : 0));
   1235             dest.writeInt(mSignalStrength);
   1236             if (mMetadata == null) {
   1237                 dest.writeByte((byte)0);
   1238             } else {
   1239                 dest.writeByte((byte)1);
   1240                 mMetadata.writeToParcel(dest, flags);
   1241             }
   1242         }
   1243 
   1244         @Override
   1245         public int describeContents() {
   1246             return 0;
   1247         }
   1248 
   1249         @Override
   1250         public String toString() {
   1251             return "ProgramInfo [mChannel=" + mChannel + ", mSubChannel=" + mSubChannel
   1252                     + ", mTuned=" + mTuned + ", mStereo=" + mStereo + ", mDigital=" + mDigital
   1253                     + ", mSignalStrength=" + mSignalStrength
   1254                     + ((mMetadata == null) ? "" : (", mMetadata=" + mMetadata.toString()))
   1255                     + "]";
   1256         }
   1257 
   1258         @Override
   1259         public int hashCode() {
   1260             final int prime = 31;
   1261             int result = 1;
   1262             result = prime * result + mChannel;
   1263             result = prime * result + mSubChannel;
   1264             result = prime * result + (mTuned ? 1 : 0);
   1265             result = prime * result + (mStereo ? 1 : 0);
   1266             result = prime * result + (mDigital ? 1 : 0);
   1267             result = prime * result + mSignalStrength;
   1268             result = prime * result + ((mMetadata == null) ? 0 : mMetadata.hashCode());
   1269             return result;
   1270         }
   1271 
   1272         @Override
   1273         public boolean equals(Object obj) {
   1274             if (this == obj)
   1275                 return true;
   1276             if (!(obj instanceof ProgramInfo))
   1277                 return false;
   1278             ProgramInfo other = (ProgramInfo) obj;
   1279             if (mChannel != other.getChannel())
   1280                 return false;
   1281             if (mSubChannel != other.getSubChannel())
   1282                 return false;
   1283             if (mTuned != other.isTuned())
   1284                 return false;
   1285             if (mStereo != other.isStereo())
   1286                 return false;
   1287             if (mDigital != other.isDigital())
   1288                 return false;
   1289             if (mSignalStrength != other.getSignalStrength())
   1290                 return false;
   1291             if (mMetadata == null) {
   1292                 if (other.getMetadata() != null)
   1293                     return false;
   1294             } else if (!mMetadata.equals(other.getMetadata()))
   1295                 return false;
   1296             return true;
   1297         }
   1298     }
   1299 
   1300 
   1301     /**
   1302      * Returns a list of descriptors for all broadcast radio modules present on the device.
   1303      * @param modules An List of {@link ModuleProperties} where the list will be returned.
   1304      * @return
   1305      * <ul>
   1306      *  <li>{@link #STATUS_OK} in case of success, </li>
   1307      *  <li>{@link #STATUS_ERROR} in case of unspecified error, </li>
   1308      *  <li>{@link #STATUS_NO_INIT} if the native service cannot be reached, </li>
   1309      *  <li>{@link #STATUS_BAD_VALUE} if modules is null, </li>
   1310      *  <li>{@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails, </li>
   1311      * </ul>
   1312      */
   1313     public native int listModules(List <ModuleProperties> modules);
   1314 
   1315     /**
   1316      * Open an interface to control a tuner on a given broadcast radio module.
   1317      * Optionally selects and applies the configuration passed as "config" argument.
   1318      * @param moduleId radio module identifier {@link ModuleProperties#getId()}. Mandatory.
   1319      * @param config desired band and configuration to apply when enabling the hardware module.
   1320      * optional, can be null.
   1321      * @param withAudio {@code true} to request a tuner with an audio source.
   1322      * This tuner is intended for live listening or recording or a radio program.
   1323      * If {@code false}, the tuner can only be used to retrieve program informations.
   1324      * @param callback {@link RadioTuner.Callback} interface. Mandatory.
   1325      * @param handler the Handler on which the callbacks will be received.
   1326      * Can be null if default handler is OK.
   1327      * @return a valid {@link RadioTuner} interface in case of success or null in case of error.
   1328      */
   1329     public RadioTuner openTuner(int moduleId, BandConfig config, boolean withAudio,
   1330             RadioTuner.Callback callback, Handler handler) {
   1331         if (callback == null) {
   1332             return null;
   1333         }
   1334         RadioModule module = new RadioModule(moduleId, config, withAudio, callback, handler);
   1335         if (module != null) {
   1336             if (!module.initCheck()) {
   1337                 module = null;
   1338             }
   1339         }
   1340         return (RadioTuner)module;
   1341     }
   1342 
   1343     private final Context mContext;
   1344 
   1345     /**
   1346      * @hide
   1347      */
   1348     public RadioManager(Context context) {
   1349         mContext = context;
   1350     }
   1351 }
   1352