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