• 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         private final boolean mEa;
461 
FmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo, boolean rds, boolean ta, boolean af, boolean ea)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          */
isStereoSupported()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          */
isRdsSupported()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          */
isTaSupported()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          */
isAfSupported()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          */
isEaSupported()500         public boolean isEaSupported() {
501             return mEa;
502         }
503 
504         /* Parcelable implementation */
FmBandDescriptor(Parcel in)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
writeToParcel(Parcel dest, int flags)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
describeContents()536         public int describeContents() {
537             return 0;
538         }
539 
540         @Override
toString()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
hashCode()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
equals(Object obj)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 
AmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo)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          */
isStereoSupported()597         public boolean isStereoSupported() {
598             return mStereo;
599         }
600 
AmBandDescriptor(Parcel in)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
writeToParcel(Parcel dest, int flags)618         public void writeToParcel(Parcel dest, int flags) {
619             super.writeToParcel(dest, flags);
620             dest.writeByte((byte) (mStereo ? 1 : 0));
621         }
622 
623         @Override
describeContents()624         public int describeContents() {
625             return 0;
626         }
627 
628         @Override
toString()629         public String toString() {
630             return "AmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo + "]";
631         }
632 
633         @Override
hashCode()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
equals(Object obj)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 
BandConfig(BandDescriptor descriptor)662         BandConfig(BandDescriptor descriptor) {
663             mDescriptor = descriptor;
664         }
665 
BandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing)666         BandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing) {
667             mDescriptor = new BandDescriptor(region, type, lowerLimit, upperLimit, spacing);
668         }
669 
BandConfig(Parcel in)670         private BandConfig(Parcel in) {
671             mDescriptor = new BandDescriptor(in);
672         }
673 
getDescriptor()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          */
getRegion()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          */
getType()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          */
getLowerLimit()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          */
getUpperLimit()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          */
getSpacing()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
writeToParcel(Parcel dest, int flags)729         public void writeToParcel(Parcel dest, int flags) {
730             mDescriptor.writeToParcel(dest, flags);
731         }
732 
733         @Override
describeContents()734         public int describeContents() {
735             return 0;
736         }
737 
738         @Override
toString()739         public String toString() {
740             return "BandConfig [ " + mDescriptor.toString() + "]";
741         }
742 
743         @Override
hashCode()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
equals(Object obj)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 
FmBandConfig(FmBandDescriptor descriptor)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 
FmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo, boolean rds, boolean ta, boolean af, boolean ea)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          */
getStereo()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          */
getRds()803         public boolean getRds() {
804             return mRds;
805         }
806 
807         /** Get Traffic announcement enable state
808          * @return the enable state.
809          */
getTa()810         public boolean getTa() {
811             return mTa;
812         }
813 
814         /** Get Alternate Frequency Switching enable state
815          * @return the enable state.
816          */
getAf()817         public boolean getAf() {
818             return mAf;
819         }
820 
821         /**
822          * Get Emergency announcement enable state
823          * @return the enable state.
824          */
getEa()825         public boolean getEa() {
826             return mEa;
827         }
828 
FmBandConfig(Parcel in)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
writeToParcel(Parcel dest, int flags)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
describeContents()860         public int describeContents() {
861             return 0;
862         }
863 
864         @Override
toString()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
hashCode()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
equals(Object obj)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              */
Builder(FmBandDescriptor descriptor)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              */
Builder(FmBandConfig config)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              */
build()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              */
setStereo(boolean state)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              */
setRds(boolean state)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              */
setTa(boolean state)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              */
setAf(boolean state)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              */
setEa(boolean state)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 
AmBandConfig(AmBandDescriptor descriptor)1010         AmBandConfig(AmBandDescriptor descriptor) {
1011             super((BandDescriptor)descriptor);
1012             mStereo = descriptor.isStereoSupported();
1013         }
1014 
AmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo)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          */
getStereo()1024         public boolean getStereo() {
1025             return mStereo;
1026         }
1027 
AmBandConfig(Parcel in)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
writeToParcel(Parcel dest, int flags)1045         public void writeToParcel(Parcel dest, int flags) {
1046             super.writeToParcel(dest, flags);
1047             dest.writeByte((byte) (mStereo ? 1 : 0));
1048         }
1049 
1050         @Override
describeContents()1051         public int describeContents() {
1052             return 0;
1053         }
1054 
1055         @Override
toString()1056         public String toString() {
1057             return "AmBandConfig [" + super.toString()
1058                     + ", mStereo=" + mStereo + "]";
1059         }
1060 
1061         @Override
hashCode()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
equals(Object obj)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              */
Builder(AmBandDescriptor descriptor)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              */
Builder(AmBandConfig config)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              */
build()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              */
setStereo(boolean state)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 
ProgramInfo(int channel, int subChannel, boolean tuned, boolean stereo, boolean digital, int signalStrength, RadioMetadata metadata)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          */
getChannel()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          */
getSubChannel()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          */
isTuned()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          */
isStereo()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          */
isDigital()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          */
getSignalStrength()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          */
getMetadata()1199         public RadioMetadata getMetadata() {
1200             return mMetadata;
1201         }
1202 
ProgramInfo(Parcel in)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
writeToParcel(Parcel dest, int flags)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
describeContents()1245         public int describeContents() {
1246             return 0;
1247         }
1248 
1249         @Override
toString()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
hashCode()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
equals(Object obj)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      */
listModules(List <ModuleProperties> modules)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      */
openTuner(int moduleId, BandConfig config, boolean withAudio, RadioTuner.Callback callback, Handler handler)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      */
RadioManager(Context context)1348     public RadioManager(Context context) {
1349         mContext = context;
1350     }
1351 }
1352