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