• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ModuleProperties(int id, int classId, String implementor, String product, String version, String serial, int numTuners, int numAudioSources, boolean isCaptureSupported, BandDescriptor[] bands)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          */
getId()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          */
getClassId()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          */
getImplementor()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          */
getProduct()153         public String getProduct() {
154             return mProduct;
155         }
156 
157         /** Human readable broadcast radio module version number
158          * @return the radio module version.
159          */
getVersion()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          */
getSerial()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          */
getNumTuners()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          */
getNumAudioSources()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          */
isCaptureSupported()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          */
getBands()202         public BandDescriptor[] getBands() {
203             return mBands;
204         }
205 
ModuleProperties(Parcel in)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
writeToParcel(Parcel dest, int flags)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
describeContents()249         public int describeContents() {
250             return 0;
251         }
252 
253         @Override
toString()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
hashCode()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
equals(Object obj)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 
BandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing)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          */
getRegion()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          */
getType()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          */
getLowerLimit()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          */
getUpperLimit()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          */
getSpacing()376         public int getSpacing() {
377             return mSpacing;
378         }
379 
BandDescriptor(Parcel in)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
writeToParcel(Parcel dest, int flags)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
describeContents()409         public int describeContents() {
410             return 0;
411         }
412 
413         @Override
toString()414         public String toString() {
415             return "BandDescriptor [mRegion=" + mRegion + ", mType=" + mType + ", mLowerLimit="
416                     + mLowerLimit + ", mUpperLimit=" + mUpperLimit + ", mSpacing=" + mSpacing + "]";
417         }
418 
419         @Override
hashCode()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
equals(Object obj)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 
FmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo, boolean rds, boolean ta, boolean af)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          */
isStereoSupported()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          */
isRdsSupported()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          */
isTaSupported()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          */
isAfSupported()491         public boolean isAfSupported() {
492             return mAf;
493         }
494 
495         /* Parcelable implementation */
FmBandDescriptor(Parcel in)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
writeToParcel(Parcel dest, int flags)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
describeContents()525         public int describeContents() {
526             return 0;
527         }
528 
529         @Override
toString()530         public String toString() {
531             return "FmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo
532                     + ", mRds=" + mRds + ", mTa=" + mTa + ", mAf=" + mAf + "]";
533         }
534 
535         @Override
hashCode()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
equals(Object obj)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 
AmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo)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          */
isStereoSupported()582         public boolean isStereoSupported() {
583             return mStereo;
584         }
585 
AmBandDescriptor(Parcel in)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
writeToParcel(Parcel dest, int flags)603         public void writeToParcel(Parcel dest, int flags) {
604             super.writeToParcel(dest, flags);
605             dest.writeByte((byte) (mStereo ? 1 : 0));
606         }
607 
608         @Override
describeContents()609         public int describeContents() {
610             return 0;
611         }
612 
613         @Override
toString()614         public String toString() {
615             return "AmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo + "]";
616         }
617 
618         @Override
hashCode()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
equals(Object obj)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 
BandConfig(BandDescriptor descriptor)647         BandConfig(BandDescriptor descriptor) {
648             mDescriptor = descriptor;
649         }
650 
BandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing)651         BandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing) {
652             mDescriptor = new BandDescriptor(region, type, lowerLimit, upperLimit, spacing);
653         }
654 
BandConfig(Parcel in)655         private BandConfig(Parcel in) {
656             mDescriptor = new BandDescriptor(in);
657         }
658 
getDescriptor()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          */
getRegion()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          */
getType()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          */
getLowerLimit()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          */
getUpperLimit()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          */
getSpacing()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
writeToParcel(Parcel dest, int flags)714         public void writeToParcel(Parcel dest, int flags) {
715             mDescriptor.writeToParcel(dest, flags);
716         }
717 
718         @Override
describeContents()719         public int describeContents() {
720             return 0;
721         }
722 
723         @Override
toString()724         public String toString() {
725             return "BandConfig [ " + mDescriptor.toString() + "]";
726         }
727 
728         @Override
hashCode()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
equals(Object obj)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 
FmBandConfig(FmBandDescriptor descriptor)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 
FmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo, boolean rds, boolean ta, boolean af)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          */
getStereo()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          */
getRds()785         public boolean getRds() {
786             return mRds;
787         }
788 
789         /** Get Traffic announcement enable state
790          * @return the enable state.
791          */
getTa()792         public boolean getTa() {
793             return mTa;
794         }
795 
796         /** Get Alternate Frequency Switching enable state
797          * @return the enable state.
798          */
getAf()799         public boolean getAf() {
800             return mAf;
801         }
802 
FmBandConfig(Parcel in)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
writeToParcel(Parcel dest, int flags)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
describeContents()832         public int describeContents() {
833             return 0;
834         }
835 
836         @Override
toString()837         public String toString() {
838             return "FmBandConfig [" + super.toString()
839                     + ", mStereo=" + mStereo + ", mRds=" + mRds + ", mTa=" + mTa
840                     + ", mAf=" + mAf + "]";
841         }
842 
843         @Override
hashCode()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
equals(Object obj)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              */
Builder(FmBandDescriptor descriptor)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              */
Builder(FmBandConfig config)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              */
build()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              */
setStereo(boolean state)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              */
setRds(boolean state)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              */
setTa(boolean state)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              */
setAf(boolean state)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 
AmBandConfig(AmBandDescriptor descriptor)967         AmBandConfig(AmBandDescriptor descriptor) {
968             super((BandDescriptor)descriptor);
969             mStereo = descriptor.isStereoSupported();
970         }
971 
AmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo)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          */
getStereo()981         public boolean getStereo() {
982             return mStereo;
983         }
984 
AmBandConfig(Parcel in)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
writeToParcel(Parcel dest, int flags)1002         public void writeToParcel(Parcel dest, int flags) {
1003             super.writeToParcel(dest, flags);
1004             dest.writeByte((byte) (mStereo ? 1 : 0));
1005         }
1006 
1007         @Override
describeContents()1008         public int describeContents() {
1009             return 0;
1010         }
1011 
1012         @Override
toString()1013         public String toString() {
1014             return "AmBandConfig [" + super.toString()
1015                     + ", mStereo=" + mStereo + "]";
1016         }
1017 
1018         @Override
hashCode()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
equals(Object obj)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              */
Builder(AmBandDescriptor descriptor)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              */
Builder(AmBandConfig config)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              */
build()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              */
setStereo(boolean state)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 
ProgramInfo(int channel, int subChannel, boolean tuned, boolean stereo, boolean digital, int signalStrength, RadioMetadata metadata)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          */
getChannel()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          */
getSubChannel()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          */
isTuned()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          */
isStereo()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          */
isDigital()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          */
getSignalStrength()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          */
getMetadata()1156         public RadioMetadata getMetadata() {
1157             return mMetadata;
1158         }
1159 
ProgramInfo(Parcel in)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
writeToParcel(Parcel dest, int flags)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
describeContents()1202         public int describeContents() {
1203             return 0;
1204         }
1205 
1206         @Override
toString()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
hashCode()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
equals(Object obj)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      */
listModules(List <ModuleProperties> modules)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      */
openTuner(int moduleId, BandConfig config, boolean withAudio, RadioTuner.Callback callback, Handler handler)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      */
RadioManager(Context context)1305     public RadioManager(Context context) {
1306         mContext = context;
1307     }
1308 }
1309