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 private final boolean mEa; 461 462 FmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing, 463 boolean stereo, boolean rds, boolean ta, boolean af, boolean ea) { 464 super(region, type, lowerLimit, upperLimit, spacing); 465 mStereo = stereo; 466 mRds = rds; 467 mTa = ta; 468 mAf = af; 469 mEa = ea; 470 } 471 472 /** Stereo is supported 473 * @return {@code true} if stereo is supported, {@code false} otherwise. 474 */ 475 public boolean isStereoSupported() { 476 return mStereo; 477 } 478 /** RDS or RBDS(if region is ITU2) is supported 479 * @return {@code true} if RDS or RBDS is supported, {@code false} otherwise. 480 */ 481 public boolean isRdsSupported() { 482 return mRds; 483 } 484 /** Traffic announcement is supported 485 * @return {@code true} if TA is supported, {@code false} otherwise. 486 */ 487 public boolean isTaSupported() { 488 return mTa; 489 } 490 /** Alternate Frequency Switching is supported 491 * @return {@code true} if AF switching is supported, {@code false} otherwise. 492 */ 493 public boolean isAfSupported() { 494 return mAf; 495 } 496 497 /** Emergency Announcement is supported 498 * @return {@code true} if Emergency annoucement is supported, {@code false} otherwise. 499 */ 500 public boolean isEaSupported() { 501 return mEa; 502 } 503 504 /* Parcelable implementation */ 505 private FmBandDescriptor(Parcel in) { 506 super(in); 507 mStereo = in.readByte() == 1; 508 mRds = in.readByte() == 1; 509 mTa = in.readByte() == 1; 510 mAf = in.readByte() == 1; 511 mEa = in.readByte() == 1; 512 } 513 514 public static final Parcelable.Creator<FmBandDescriptor> CREATOR 515 = new Parcelable.Creator<FmBandDescriptor>() { 516 public FmBandDescriptor createFromParcel(Parcel in) { 517 return new FmBandDescriptor(in); 518 } 519 520 public FmBandDescriptor[] newArray(int size) { 521 return new FmBandDescriptor[size]; 522 } 523 }; 524 525 @Override 526 public void writeToParcel(Parcel dest, int flags) { 527 super.writeToParcel(dest, flags); 528 dest.writeByte((byte) (mStereo ? 1 : 0)); 529 dest.writeByte((byte) (mRds ? 1 : 0)); 530 dest.writeByte((byte) (mTa ? 1 : 0)); 531 dest.writeByte((byte) (mAf ? 1 : 0)); 532 dest.writeByte((byte) (mEa ? 1 : 0)); 533 } 534 535 @Override 536 public int describeContents() { 537 return 0; 538 } 539 540 @Override 541 public String toString() { 542 return "FmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo 543 + ", mRds=" + mRds + ", mTa=" + mTa + ", mAf=" + mAf + 544 ", mEa =" + mEa + "]"; 545 } 546 547 @Override 548 public int hashCode() { 549 final int prime = 31; 550 int result = super.hashCode(); 551 result = prime * result + (mStereo ? 1 : 0); 552 result = prime * result + (mRds ? 1 : 0); 553 result = prime * result + (mTa ? 1 : 0); 554 result = prime * result + (mAf ? 1 : 0); 555 result = prime * result + (mEa ? 1 : 0); 556 return result; 557 } 558 559 @Override 560 public boolean equals(Object obj) { 561 if (this == obj) 562 return true; 563 if (!super.equals(obj)) 564 return false; 565 if (!(obj instanceof FmBandDescriptor)) 566 return false; 567 FmBandDescriptor other = (FmBandDescriptor) obj; 568 if (mStereo != other.isStereoSupported()) 569 return false; 570 if (mRds != other.isRdsSupported()) 571 return false; 572 if (mTa != other.isTaSupported()) 573 return false; 574 if (mAf != other.isAfSupported()) 575 return false; 576 if (mEa != other.isEaSupported()) 577 return false; 578 return true; 579 } 580 } 581 582 /** AM band descriptor. 583 * @see #BAND_AM */ 584 public static class AmBandDescriptor extends BandDescriptor { 585 586 private final boolean mStereo; 587 588 AmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing, 589 boolean stereo) { 590 super(region, type, lowerLimit, upperLimit, spacing); 591 mStereo = stereo; 592 } 593 594 /** Stereo is supported 595 * @return {@code true} if stereo is supported, {@code false} otherwise. 596 */ 597 public boolean isStereoSupported() { 598 return mStereo; 599 } 600 601 private AmBandDescriptor(Parcel in) { 602 super(in); 603 mStereo = in.readByte() == 1; 604 } 605 606 public static final Parcelable.Creator<AmBandDescriptor> CREATOR 607 = new Parcelable.Creator<AmBandDescriptor>() { 608 public AmBandDescriptor createFromParcel(Parcel in) { 609 return new AmBandDescriptor(in); 610 } 611 612 public AmBandDescriptor[] newArray(int size) { 613 return new AmBandDescriptor[size]; 614 } 615 }; 616 617 @Override 618 public void writeToParcel(Parcel dest, int flags) { 619 super.writeToParcel(dest, flags); 620 dest.writeByte((byte) (mStereo ? 1 : 0)); 621 } 622 623 @Override 624 public int describeContents() { 625 return 0; 626 } 627 628 @Override 629 public String toString() { 630 return "AmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo + "]"; 631 } 632 633 @Override 634 public int hashCode() { 635 final int prime = 31; 636 int result = super.hashCode(); 637 result = prime * result + (mStereo ? 1 : 0); 638 return result; 639 } 640 641 @Override 642 public boolean equals(Object obj) { 643 if (this == obj) 644 return true; 645 if (!super.equals(obj)) 646 return false; 647 if (!(obj instanceof AmBandDescriptor)) 648 return false; 649 AmBandDescriptor other = (AmBandDescriptor) obj; 650 if (mStereo != other.isStereoSupported()) 651 return false; 652 return true; 653 } 654 } 655 656 657 /** Radio band configuration. */ 658 public static class BandConfig implements Parcelable { 659 660 final BandDescriptor mDescriptor; 661 662 BandConfig(BandDescriptor descriptor) { 663 mDescriptor = descriptor; 664 } 665 666 BandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing) { 667 mDescriptor = new BandDescriptor(region, type, lowerLimit, upperLimit, spacing); 668 } 669 670 private BandConfig(Parcel in) { 671 mDescriptor = new BandDescriptor(in); 672 } 673 674 BandDescriptor getDescriptor() { 675 return mDescriptor; 676 } 677 678 /** Region this band applies to. E.g. {@link #REGION_ITU_1} 679 * @return the region associated with this band. 680 */ 681 public int getRegion() { 682 return mDescriptor.getRegion(); 683 } 684 /** Band type, e.g {@link #BAND_FM}. Defines the subclass this descriptor can be cast to: 685 * <ul> 686 * <li>{@link #BAND_FM} or {@link #BAND_FM_HD} cast to {@link FmBandDescriptor}, </li> 687 * <li>{@link #BAND_AM} cast to {@link AmBandDescriptor}, </li> 688 * </ul> 689 * @return the band type. 690 */ 691 public int getType() { 692 return mDescriptor.getType(); 693 } 694 /** Lower band limit expressed in units according to band type. 695 * Currently all defined band types express channels as frequency in kHz 696 * @return the lower band limit. 697 */ 698 public int getLowerLimit() { 699 return mDescriptor.getLowerLimit(); 700 } 701 /** Upper band limit expressed in units according to band type. 702 * Currently all defined band types express channels as frequency in kHz 703 * @return the upper band limit. 704 */ 705 public int getUpperLimit() { 706 return mDescriptor.getUpperLimit(); 707 } 708 /** Channel spacing in units according to band type. 709 * Currently all defined band types express channels as frequency in kHz 710 * @return the channel spacing. 711 */ 712 public int getSpacing() { 713 return mDescriptor.getSpacing(); 714 } 715 716 717 public static final Parcelable.Creator<BandConfig> CREATOR 718 = new Parcelable.Creator<BandConfig>() { 719 public BandConfig createFromParcel(Parcel in) { 720 return new BandConfig(in); 721 } 722 723 public BandConfig[] newArray(int size) { 724 return new BandConfig[size]; 725 } 726 }; 727 728 @Override 729 public void writeToParcel(Parcel dest, int flags) { 730 mDescriptor.writeToParcel(dest, flags); 731 } 732 733 @Override 734 public int describeContents() { 735 return 0; 736 } 737 738 @Override 739 public String toString() { 740 return "BandConfig [ " + mDescriptor.toString() + "]"; 741 } 742 743 @Override 744 public int hashCode() { 745 final int prime = 31; 746 int result = 1; 747 result = prime * result + mDescriptor.hashCode(); 748 return result; 749 } 750 751 @Override 752 public boolean equals(Object obj) { 753 if (this == obj) 754 return true; 755 if (!(obj instanceof BandConfig)) 756 return false; 757 BandConfig other = (BandConfig) obj; 758 if (mDescriptor != other.getDescriptor()) 759 return false; 760 return true; 761 } 762 } 763 764 /** FM band configuration. 765 * @see #BAND_FM 766 * @see #BAND_FM_HD */ 767 public static class FmBandConfig extends BandConfig { 768 private final boolean mStereo; 769 private final boolean mRds; 770 private final boolean mTa; 771 private final boolean mAf; 772 private final boolean mEa; 773 774 FmBandConfig(FmBandDescriptor descriptor) { 775 super((BandDescriptor)descriptor); 776 mStereo = descriptor.isStereoSupported(); 777 mRds = descriptor.isRdsSupported(); 778 mTa = descriptor.isTaSupported(); 779 mAf = descriptor.isAfSupported(); 780 mEa = descriptor.isEaSupported(); 781 } 782 783 FmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing, 784 boolean stereo, boolean rds, boolean ta, boolean af, boolean ea) { 785 super(region, type, lowerLimit, upperLimit, spacing); 786 mStereo = stereo; 787 mRds = rds; 788 mTa = ta; 789 mAf = af; 790 mEa = ea; 791 } 792 793 /** Get stereo enable state 794 * @return the enable state. 795 */ 796 public boolean getStereo() { 797 return mStereo; 798 } 799 800 /** Get RDS or RBDS(if region is ITU2) enable state 801 * @return the enable state. 802 */ 803 public boolean getRds() { 804 return mRds; 805 } 806 807 /** Get Traffic announcement enable state 808 * @return the enable state. 809 */ 810 public boolean getTa() { 811 return mTa; 812 } 813 814 /** Get Alternate Frequency Switching enable state 815 * @return the enable state. 816 */ 817 public boolean getAf() { 818 return mAf; 819 } 820 821 /** 822 * Get Emergency announcement enable state 823 * @return the enable state. 824 */ 825 public boolean getEa() { 826 return mEa; 827 } 828 829 private FmBandConfig(Parcel in) { 830 super(in); 831 mStereo = in.readByte() == 1; 832 mRds = in.readByte() == 1; 833 mTa = in.readByte() == 1; 834 mAf = in.readByte() == 1; 835 mEa = in.readByte() == 1; 836 } 837 838 public static final Parcelable.Creator<FmBandConfig> CREATOR 839 = new Parcelable.Creator<FmBandConfig>() { 840 public FmBandConfig createFromParcel(Parcel in) { 841 return new FmBandConfig(in); 842 } 843 844 public FmBandConfig[] newArray(int size) { 845 return new FmBandConfig[size]; 846 } 847 }; 848 849 @Override 850 public void writeToParcel(Parcel dest, int flags) { 851 super.writeToParcel(dest, flags); 852 dest.writeByte((byte) (mStereo ? 1 : 0)); 853 dest.writeByte((byte) (mRds ? 1 : 0)); 854 dest.writeByte((byte) (mTa ? 1 : 0)); 855 dest.writeByte((byte) (mAf ? 1 : 0)); 856 dest.writeByte((byte) (mEa ? 1 : 0)); 857 } 858 859 @Override 860 public int describeContents() { 861 return 0; 862 } 863 864 @Override 865 public String toString() { 866 return "FmBandConfig [" + super.toString() 867 + ", mStereo=" + mStereo + ", mRds=" + mRds + ", mTa=" + mTa 868 + ", mAf=" + mAf + ", mEa =" + mEa + "]"; 869 } 870 871 @Override 872 public int hashCode() { 873 final int prime = 31; 874 int result = super.hashCode(); 875 result = prime * result + (mStereo ? 1 : 0); 876 result = prime * result + (mRds ? 1 : 0); 877 result = prime * result + (mTa ? 1 : 0); 878 result = prime * result + (mAf ? 1 : 0); 879 result = prime * result + (mEa ? 1 : 0); 880 return result; 881 } 882 883 @Override 884 public boolean equals(Object obj) { 885 if (this == obj) 886 return true; 887 if (!super.equals(obj)) 888 return false; 889 if (!(obj instanceof FmBandConfig)) 890 return false; 891 FmBandConfig other = (FmBandConfig) obj; 892 if (mStereo != other.mStereo) 893 return false; 894 if (mRds != other.mRds) 895 return false; 896 if (mTa != other.mTa) 897 return false; 898 if (mAf != other.mAf) 899 return false; 900 if (mEa != other.mEa) 901 return false; 902 return true; 903 } 904 905 /** 906 * Builder class for {@link FmBandConfig} objects. 907 */ 908 public static class Builder { 909 private final BandDescriptor mDescriptor; 910 private boolean mStereo; 911 private boolean mRds; 912 private boolean mTa; 913 private boolean mAf; 914 private boolean mEa; 915 916 /** 917 * Constructs a new Builder with the defaults from an {@link FmBandDescriptor} . 918 * @param descriptor the FmBandDescriptor defaults are read from . 919 */ 920 public Builder(FmBandDescriptor descriptor) { 921 mDescriptor = new BandDescriptor(descriptor.getRegion(), descriptor.getType(), 922 descriptor.getLowerLimit(), descriptor.getUpperLimit(), 923 descriptor.getSpacing()); 924 mStereo = descriptor.isStereoSupported(); 925 mRds = descriptor.isRdsSupported(); 926 mTa = descriptor.isTaSupported(); 927 mAf = descriptor.isAfSupported(); 928 mEa = descriptor.isEaSupported(); 929 } 930 931 /** 932 * Constructs a new Builder from a given {@link FmBandConfig} 933 * @param config the FmBandConfig object whose data will be reused in the new Builder. 934 */ 935 public Builder(FmBandConfig config) { 936 mDescriptor = new BandDescriptor(config.getRegion(), config.getType(), 937 config.getLowerLimit(), config.getUpperLimit(), config.getSpacing()); 938 mStereo = config.getStereo(); 939 mRds = config.getRds(); 940 mTa = config.getTa(); 941 mAf = config.getAf(); 942 mEa = config.getEa(); 943 } 944 945 /** 946 * Combines all of the parameters that have been set and return a new 947 * {@link FmBandConfig} object. 948 * @return a new {@link FmBandConfig} object 949 */ 950 public FmBandConfig build() { 951 FmBandConfig config = new FmBandConfig(mDescriptor.getRegion(), 952 mDescriptor.getType(), mDescriptor.getLowerLimit(), 953 mDescriptor.getUpperLimit(), mDescriptor.getSpacing(), 954 mStereo, mRds, mTa, mAf, mEa); 955 return config; 956 } 957 958 /** Set stereo enable state 959 * @param state The new enable state. 960 * @return the same Builder instance. 961 */ 962 public Builder setStereo(boolean state) { 963 mStereo = state; 964 return this; 965 } 966 967 /** Set RDS or RBDS(if region is ITU2) enable state 968 * @param state The new enable state. 969 * @return the same Builder instance. 970 */ 971 public Builder setRds(boolean state) { 972 mRds = state; 973 return this; 974 } 975 976 /** Set Traffic announcement enable state 977 * @param state The new enable state. 978 * @return the same Builder instance. 979 */ 980 public Builder setTa(boolean state) { 981 mTa = state; 982 return this; 983 } 984 985 /** Set Alternate Frequency Switching enable state 986 * @param state The new enable state. 987 * @return the same Builder instance. 988 */ 989 public Builder setAf(boolean state) { 990 mAf = state; 991 return this; 992 } 993 994 /** Set Emergency Announcement enable state 995 * @param state The new enable state. 996 * @return the same Builder instance. 997 */ 998 public Builder setEa(boolean state) { 999 mEa = state; 1000 return this; 1001 } 1002 }; 1003 } 1004 1005 /** AM band configuration. 1006 * @see #BAND_AM */ 1007 public static class AmBandConfig extends BandConfig { 1008 private final boolean mStereo; 1009 1010 AmBandConfig(AmBandDescriptor descriptor) { 1011 super((BandDescriptor)descriptor); 1012 mStereo = descriptor.isStereoSupported(); 1013 } 1014 1015 AmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing, 1016 boolean stereo) { 1017 super(region, type, lowerLimit, upperLimit, spacing); 1018 mStereo = stereo; 1019 } 1020 1021 /** Get stereo enable state 1022 * @return the enable state. 1023 */ 1024 public boolean getStereo() { 1025 return mStereo; 1026 } 1027 1028 private AmBandConfig(Parcel in) { 1029 super(in); 1030 mStereo = in.readByte() == 1; 1031 } 1032 1033 public static final Parcelable.Creator<AmBandConfig> CREATOR 1034 = new Parcelable.Creator<AmBandConfig>() { 1035 public AmBandConfig createFromParcel(Parcel in) { 1036 return new AmBandConfig(in); 1037 } 1038 1039 public AmBandConfig[] newArray(int size) { 1040 return new AmBandConfig[size]; 1041 } 1042 }; 1043 1044 @Override 1045 public void writeToParcel(Parcel dest, int flags) { 1046 super.writeToParcel(dest, flags); 1047 dest.writeByte((byte) (mStereo ? 1 : 0)); 1048 } 1049 1050 @Override 1051 public int describeContents() { 1052 return 0; 1053 } 1054 1055 @Override 1056 public String toString() { 1057 return "AmBandConfig [" + super.toString() 1058 + ", mStereo=" + mStereo + "]"; 1059 } 1060 1061 @Override 1062 public int hashCode() { 1063 final int prime = 31; 1064 int result = super.hashCode(); 1065 result = prime * result + (mStereo ? 1 : 0); 1066 return result; 1067 } 1068 1069 @Override 1070 public boolean equals(Object obj) { 1071 if (this == obj) 1072 return true; 1073 if (!super.equals(obj)) 1074 return false; 1075 if (!(obj instanceof AmBandConfig)) 1076 return false; 1077 AmBandConfig other = (AmBandConfig) obj; 1078 if (mStereo != other.getStereo()) 1079 return false; 1080 return true; 1081 } 1082 1083 /** 1084 * Builder class for {@link AmBandConfig} objects. 1085 */ 1086 public static class Builder { 1087 private final BandDescriptor mDescriptor; 1088 private boolean mStereo; 1089 1090 /** 1091 * Constructs a new Builder with the defaults from an {@link AmBandDescriptor} . 1092 * @param descriptor the FmBandDescriptor defaults are read from . 1093 */ 1094 public Builder(AmBandDescriptor descriptor) { 1095 mDescriptor = new BandDescriptor(descriptor.getRegion(), descriptor.getType(), 1096 descriptor.getLowerLimit(), descriptor.getUpperLimit(), 1097 descriptor.getSpacing()); 1098 mStereo = descriptor.isStereoSupported(); 1099 } 1100 1101 /** 1102 * Constructs a new Builder from a given {@link AmBandConfig} 1103 * @param config the FmBandConfig object whose data will be reused in the new Builder. 1104 */ 1105 public Builder(AmBandConfig config) { 1106 mDescriptor = new BandDescriptor(config.getRegion(), config.getType(), 1107 config.getLowerLimit(), config.getUpperLimit(), config.getSpacing()); 1108 mStereo = config.getStereo(); 1109 } 1110 1111 /** 1112 * Combines all of the parameters that have been set and return a new 1113 * {@link AmBandConfig} object. 1114 * @return a new {@link AmBandConfig} object 1115 */ 1116 public AmBandConfig build() { 1117 AmBandConfig config = new AmBandConfig(mDescriptor.getRegion(), 1118 mDescriptor.getType(), mDescriptor.getLowerLimit(), 1119 mDescriptor.getUpperLimit(), mDescriptor.getSpacing(), 1120 mStereo); 1121 return config; 1122 } 1123 1124 /** Set stereo enable state 1125 * @param state The new enable state. 1126 * @return the same Builder instance. 1127 */ 1128 public Builder setStereo(boolean state) { 1129 mStereo = state; 1130 return this; 1131 } 1132 }; 1133 } 1134 1135 /** Radio program information returned by 1136 * {@link RadioTuner#getProgramInformation(RadioManager.ProgramInfo[])} */ 1137 public static class ProgramInfo implements Parcelable { 1138 1139 private final int mChannel; 1140 private final int mSubChannel; 1141 private final boolean mTuned; 1142 private final boolean mStereo; 1143 private final boolean mDigital; 1144 private final int mSignalStrength; 1145 private final RadioMetadata mMetadata; 1146 1147 ProgramInfo(int channel, int subChannel, boolean tuned, boolean stereo, 1148 boolean digital, int signalStrength, RadioMetadata metadata) { 1149 mChannel = channel; 1150 mSubChannel = subChannel; 1151 mTuned = tuned; 1152 mStereo = stereo; 1153 mDigital = digital; 1154 mSignalStrength = signalStrength; 1155 mMetadata = metadata; 1156 } 1157 1158 /** Main channel expressed in units according to band type. 1159 * Currently all defined band types express channels as frequency in kHz 1160 * @return the program channel 1161 */ 1162 public int getChannel() { 1163 return mChannel; 1164 } 1165 /** Sub channel ID. E.g 1 for HD radio HD1 1166 * @return the program sub channel 1167 */ 1168 public int getSubChannel() { 1169 return mSubChannel; 1170 } 1171 /** {@code true} if the tuner is currently tuned on a valid station 1172 * @return {@code true} if currently tuned, {@code false} otherwise. 1173 */ 1174 public boolean isTuned() { 1175 return mTuned; 1176 } 1177 /** {@code true} if the received program is stereo 1178 * @return {@code true} if stereo, {@code false} otherwise. 1179 */ 1180 public boolean isStereo() { 1181 return mStereo; 1182 } 1183 /** {@code true} if the received program is digital (e.g HD radio) 1184 * @return {@code true} if digital, {@code false} otherwise. 1185 */ 1186 public boolean isDigital() { 1187 return mDigital; 1188 } 1189 /** Signal strength indicator from 0 (no signal) to 100 (excellent) 1190 * @return the signal strength indication. 1191 */ 1192 public int getSignalStrength() { 1193 return mSignalStrength; 1194 } 1195 /** Metadata currently received from this station. 1196 * null if no metadata have been received 1197 * @return current meta data received from this program. 1198 */ 1199 public RadioMetadata getMetadata() { 1200 return mMetadata; 1201 } 1202 1203 private ProgramInfo(Parcel in) { 1204 mChannel = in.readInt(); 1205 mSubChannel = in.readInt(); 1206 mTuned = in.readByte() == 1; 1207 mStereo = in.readByte() == 1; 1208 mDigital = in.readByte() == 1; 1209 mSignalStrength = in.readInt(); 1210 if (in.readByte() == 1) { 1211 mMetadata = RadioMetadata.CREATOR.createFromParcel(in); 1212 } else { 1213 mMetadata = null; 1214 } 1215 } 1216 1217 public static final Parcelable.Creator<ProgramInfo> CREATOR 1218 = new Parcelable.Creator<ProgramInfo>() { 1219 public ProgramInfo createFromParcel(Parcel in) { 1220 return new ProgramInfo(in); 1221 } 1222 1223 public ProgramInfo[] newArray(int size) { 1224 return new ProgramInfo[size]; 1225 } 1226 }; 1227 1228 @Override 1229 public void writeToParcel(Parcel dest, int flags) { 1230 dest.writeInt(mChannel); 1231 dest.writeInt(mSubChannel); 1232 dest.writeByte((byte)(mTuned ? 1 : 0)); 1233 dest.writeByte((byte)(mStereo ? 1 : 0)); 1234 dest.writeByte((byte)(mDigital ? 1 : 0)); 1235 dest.writeInt(mSignalStrength); 1236 if (mMetadata == null) { 1237 dest.writeByte((byte)0); 1238 } else { 1239 dest.writeByte((byte)1); 1240 mMetadata.writeToParcel(dest, flags); 1241 } 1242 } 1243 1244 @Override 1245 public int describeContents() { 1246 return 0; 1247 } 1248 1249 @Override 1250 public String toString() { 1251 return "ProgramInfo [mChannel=" + mChannel + ", mSubChannel=" + mSubChannel 1252 + ", mTuned=" + mTuned + ", mStereo=" + mStereo + ", mDigital=" + mDigital 1253 + ", mSignalStrength=" + mSignalStrength 1254 + ((mMetadata == null) ? "" : (", mMetadata=" + mMetadata.toString())) 1255 + "]"; 1256 } 1257 1258 @Override 1259 public int hashCode() { 1260 final int prime = 31; 1261 int result = 1; 1262 result = prime * result + mChannel; 1263 result = prime * result + mSubChannel; 1264 result = prime * result + (mTuned ? 1 : 0); 1265 result = prime * result + (mStereo ? 1 : 0); 1266 result = prime * result + (mDigital ? 1 : 0); 1267 result = prime * result + mSignalStrength; 1268 result = prime * result + ((mMetadata == null) ? 0 : mMetadata.hashCode()); 1269 return result; 1270 } 1271 1272 @Override 1273 public boolean equals(Object obj) { 1274 if (this == obj) 1275 return true; 1276 if (!(obj instanceof ProgramInfo)) 1277 return false; 1278 ProgramInfo other = (ProgramInfo) obj; 1279 if (mChannel != other.getChannel()) 1280 return false; 1281 if (mSubChannel != other.getSubChannel()) 1282 return false; 1283 if (mTuned != other.isTuned()) 1284 return false; 1285 if (mStereo != other.isStereo()) 1286 return false; 1287 if (mDigital != other.isDigital()) 1288 return false; 1289 if (mSignalStrength != other.getSignalStrength()) 1290 return false; 1291 if (mMetadata == null) { 1292 if (other.getMetadata() != null) 1293 return false; 1294 } else if (!mMetadata.equals(other.getMetadata())) 1295 return false; 1296 return true; 1297 } 1298 } 1299 1300 1301 /** 1302 * Returns a list of descriptors for all broadcast radio modules present on the device. 1303 * @param modules An List of {@link ModuleProperties} where the list will be returned. 1304 * @return 1305 * <ul> 1306 * <li>{@link #STATUS_OK} in case of success, </li> 1307 * <li>{@link #STATUS_ERROR} in case of unspecified error, </li> 1308 * <li>{@link #STATUS_NO_INIT} if the native service cannot be reached, </li> 1309 * <li>{@link #STATUS_BAD_VALUE} if modules is null, </li> 1310 * <li>{@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails, </li> 1311 * </ul> 1312 */ 1313 public native int listModules(List <ModuleProperties> modules); 1314 1315 /** 1316 * Open an interface to control a tuner on a given broadcast radio module. 1317 * Optionally selects and applies the configuration passed as "config" argument. 1318 * @param moduleId radio module identifier {@link ModuleProperties#getId()}. Mandatory. 1319 * @param config desired band and configuration to apply when enabling the hardware module. 1320 * optional, can be null. 1321 * @param withAudio {@code true} to request a tuner with an audio source. 1322 * This tuner is intended for live listening or recording or a radio program. 1323 * If {@code false}, the tuner can only be used to retrieve program informations. 1324 * @param callback {@link RadioTuner.Callback} interface. Mandatory. 1325 * @param handler the Handler on which the callbacks will be received. 1326 * Can be null if default handler is OK. 1327 * @return a valid {@link RadioTuner} interface in case of success or null in case of error. 1328 */ 1329 public RadioTuner openTuner(int moduleId, BandConfig config, boolean withAudio, 1330 RadioTuner.Callback callback, Handler handler) { 1331 if (callback == null) { 1332 return null; 1333 } 1334 RadioModule module = new RadioModule(moduleId, config, withAudio, callback, handler); 1335 if (module != null) { 1336 if (!module.initCheck()) { 1337 module = null; 1338 } 1339 } 1340 return (RadioTuner)module; 1341 } 1342 1343 private final Context mContext; 1344 1345 /** 1346 * @hide 1347 */ 1348 public RadioManager(Context context) { 1349 mContext = context; 1350 } 1351} 1352