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