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.annotation.SystemService; 21 import android.content.Context; 22 import android.os.Handler; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 import java.util.List; 26 import 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) 37 public 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 ModuleProperties(int id, int classId, String implementor, String product, String version, String serial, int numTuners, int numAudioSources, boolean isCaptureSupported, BandDescriptor[] bands)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 */ getId()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 */ getClassId()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 */ getImplementor()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 */ getProduct()155 public String getProduct() { 156 return mProduct; 157 } 158 159 /** Human readable broadcast radio module version number 160 * @return the radio module version. 161 */ getVersion()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 */ getSerial()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 */ getNumTuners()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 */ getNumAudioSources()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 */ isCaptureSupported()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 */ getBands()204 public BandDescriptor[] getBands() { 205 return mBands; 206 } 207 ModuleProperties(Parcel in)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 writeToParcel(Parcel dest, int flags)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 describeContents()251 public int describeContents() { 252 return 0; 253 } 254 255 @Override toString()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 hashCode()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 equals(Object obj)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 BandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing)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 */ getRegion()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 */ getType()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 */ getLowerLimit()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 */ getUpperLimit()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 */ getSpacing()378 public int getSpacing() { 379 return mSpacing; 380 } 381 BandDescriptor(Parcel in)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 writeToParcel(Parcel dest, int flags)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 describeContents()411 public int describeContents() { 412 return 0; 413 } 414 415 @Override toString()416 public String toString() { 417 return "BandDescriptor [mRegion=" + mRegion + ", mType=" + mType + ", mLowerLimit=" 418 + mLowerLimit + ", mUpperLimit=" + mUpperLimit + ", mSpacing=" + mSpacing + "]"; 419 } 420 421 @Override hashCode()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 equals(Object obj)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 FmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo, boolean rds, boolean ta, boolean af, boolean ea)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 */ isStereoSupported()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 */ isRdsSupported()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 */ isTaSupported()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 */ isAfSupported()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 */ isEaSupported()502 public boolean isEaSupported() { 503 return mEa; 504 } 505 506 /* Parcelable implementation */ FmBandDescriptor(Parcel in)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 writeToParcel(Parcel dest, int flags)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 describeContents()538 public int describeContents() { 539 return 0; 540 } 541 542 @Override toString()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 hashCode()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 equals(Object obj)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 AmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo)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 */ isStereoSupported()599 public boolean isStereoSupported() { 600 return mStereo; 601 } 602 AmBandDescriptor(Parcel in)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 writeToParcel(Parcel dest, int flags)620 public void writeToParcel(Parcel dest, int flags) { 621 super.writeToParcel(dest, flags); 622 dest.writeByte((byte) (mStereo ? 1 : 0)); 623 } 624 625 @Override describeContents()626 public int describeContents() { 627 return 0; 628 } 629 630 @Override toString()631 public String toString() { 632 return "AmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo + "]"; 633 } 634 635 @Override hashCode()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 equals(Object obj)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 BandConfig(BandDescriptor descriptor)664 BandConfig(BandDescriptor descriptor) { 665 mDescriptor = descriptor; 666 } 667 BandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing)668 BandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing) { 669 mDescriptor = new BandDescriptor(region, type, lowerLimit, upperLimit, spacing); 670 } 671 BandConfig(Parcel in)672 private BandConfig(Parcel in) { 673 mDescriptor = new BandDescriptor(in); 674 } 675 getDescriptor()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 */ getRegion()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 */ getType()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 */ getLowerLimit()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 */ getUpperLimit()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 */ getSpacing()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 writeToParcel(Parcel dest, int flags)731 public void writeToParcel(Parcel dest, int flags) { 732 mDescriptor.writeToParcel(dest, flags); 733 } 734 735 @Override describeContents()736 public int describeContents() { 737 return 0; 738 } 739 740 @Override toString()741 public String toString() { 742 return "BandConfig [ " + mDescriptor.toString() + "]"; 743 } 744 745 @Override hashCode()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 equals(Object obj)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 FmBandConfig(FmBandDescriptor descriptor)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 FmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo, boolean rds, boolean ta, boolean af, boolean ea)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 */ getStereo()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 */ getRds()805 public boolean getRds() { 806 return mRds; 807 } 808 809 /** Get Traffic announcement enable state 810 * @return the enable state. 811 */ getTa()812 public boolean getTa() { 813 return mTa; 814 } 815 816 /** Get Alternate Frequency Switching enable state 817 * @return the enable state. 818 */ getAf()819 public boolean getAf() { 820 return mAf; 821 } 822 823 /** 824 * Get Emergency announcement enable state 825 * @return the enable state. 826 */ getEa()827 public boolean getEa() { 828 return mEa; 829 } 830 FmBandConfig(Parcel in)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 writeToParcel(Parcel dest, int flags)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 describeContents()862 public int describeContents() { 863 return 0; 864 } 865 866 @Override toString()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 hashCode()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 equals(Object obj)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 */ Builder(FmBandDescriptor descriptor)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 */ Builder(FmBandConfig config)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 */ build()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 */ setStereo(boolean state)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 */ setRds(boolean state)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 */ setTa(boolean state)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 */ setAf(boolean state)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 */ setEa(boolean state)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 AmBandConfig(AmBandDescriptor descriptor)1012 AmBandConfig(AmBandDescriptor descriptor) { 1013 super((BandDescriptor)descriptor); 1014 mStereo = descriptor.isStereoSupported(); 1015 } 1016 AmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo)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 */ getStereo()1026 public boolean getStereo() { 1027 return mStereo; 1028 } 1029 AmBandConfig(Parcel in)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 writeToParcel(Parcel dest, int flags)1047 public void writeToParcel(Parcel dest, int flags) { 1048 super.writeToParcel(dest, flags); 1049 dest.writeByte((byte) (mStereo ? 1 : 0)); 1050 } 1051 1052 @Override describeContents()1053 public int describeContents() { 1054 return 0; 1055 } 1056 1057 @Override toString()1058 public String toString() { 1059 return "AmBandConfig [" + super.toString() 1060 + ", mStereo=" + mStereo + "]"; 1061 } 1062 1063 @Override hashCode()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 equals(Object obj)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 */ Builder(AmBandDescriptor descriptor)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 */ Builder(AmBandConfig config)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 */ build()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 */ setStereo(boolean state)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 ProgramInfo(int channel, int subChannel, boolean tuned, boolean stereo, boolean digital, int signalStrength, RadioMetadata metadata)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 */ getChannel()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 */ getSubChannel()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 */ isTuned()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 */ isStereo()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 */ isDigital()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 */ getSignalStrength()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 */ getMetadata()1201 public RadioMetadata getMetadata() { 1202 return mMetadata; 1203 } 1204 ProgramInfo(Parcel in)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 writeToParcel(Parcel dest, int flags)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 describeContents()1247 public int describeContents() { 1248 return 0; 1249 } 1250 1251 @Override toString()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 hashCode()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 equals(Object obj)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 */ listModules(List <ModuleProperties> modules)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 */ openTuner(int moduleId, BandConfig config, boolean withAudio, RadioTuner.Callback callback, Handler handler)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 */ RadioManager(Context context)1350 public RadioManager(Context context) { 1351 mContext = context; 1352 } 1353 } 1354