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