1 /** 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.hardware.radio; 18 19 import android.annotation.SystemApi; 20 import android.content.Context; 21 import android.os.Handler; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 import java.util.List; 25 import java.util.Arrays; 26 27 /** 28 * The RadioManager class allows to control a broadcast radio tuner present on the device. 29 * It provides data structures and methods to query for available radio modules, list their 30 * properties and open an interface to control tuning operations and receive callbacks when 31 * asynchronous operations complete or events occur. 32 * @hide 33 */ 34 @SystemApi 35 public class RadioManager { 36 37 /** Method return status: successful operation */ 38 public static final int STATUS_OK = 0; 39 /** Method return status: unspecified error */ 40 public static final int STATUS_ERROR = Integer.MIN_VALUE; 41 /** Method return status: permission denied */ 42 public static final int STATUS_PERMISSION_DENIED = -1; 43 /** Method return status: initialization failure */ 44 public static final int STATUS_NO_INIT = -19; 45 /** Method return status: invalid argument provided */ 46 public static final int STATUS_BAD_VALUE = -22; 47 /** Method return status: cannot reach service */ 48 public static final int STATUS_DEAD_OBJECT = -32; 49 /** Method return status: invalid or out of sequence operation */ 50 public static final int STATUS_INVALID_OPERATION = -38; 51 /** Method return status: time out before operation completion */ 52 public static final int STATUS_TIMED_OUT = -110; 53 54 55 // keep in sync with radio_class_t in /system/core/incluse/system/radio.h 56 /** Radio module class supporting FM (including HD radio) and AM */ 57 public static final int CLASS_AM_FM = 0; 58 /** Radio module class supporting satellite radio */ 59 public static final int CLASS_SAT = 1; 60 /** Radio module class supporting Digital terrestrial radio */ 61 public static final int CLASS_DT = 2; 62 63 // keep in sync with radio_band_t in /system/core/incluse/system/radio.h 64 /** AM radio band (LW/MW/SW). 65 * @see BandDescriptor */ 66 public static final int BAND_AM = 0; 67 /** FM radio band. 68 * @see BandDescriptor */ 69 public static final int BAND_FM = 1; 70 /** FM HD radio or DRM band. 71 * @see BandDescriptor */ 72 public static final int BAND_FM_HD = 2; 73 /** AM HD radio or DRM band. 74 * @see BandDescriptor */ 75 public static final int BAND_AM_HD = 3; 76 77 // keep in sync with radio_region_t in /system/core/incluse/system/radio.h 78 /** Africa, Europe. 79 * @see BandDescriptor */ 80 public static final int REGION_ITU_1 = 0; 81 /** Americas. 82 * @see BandDescriptor */ 83 public static final int REGION_ITU_2 = 1; 84 /** Russia. 85 * @see BandDescriptor */ 86 public static final int REGION_OIRT = 2; 87 /** Japan. 88 * @see BandDescriptor */ 89 public static final int REGION_JAPAN = 3; 90 /** Korea. 91 * @see BandDescriptor */ 92 public static final int REGION_KOREA = 4; 93 94 /***************************************************************************** 95 * Lists properties, options and radio bands supported by a given broadcast radio module. 96 * Each module has a unique ID used to address it when calling RadioManager APIs. 97 * Module properties are returned by {@link #listModules(List <ModuleProperties>)} method. 98 ****************************************************************************/ 99 public static class ModuleProperties implements Parcelable { 100 101 private final int mId; 102 private final int mClassId; 103 private final String mImplementor; 104 private final String mProduct; 105 private final String mVersion; 106 private final String mSerial; 107 private final int mNumTuners; 108 private final int mNumAudioSources; 109 private final boolean mIsCaptureSupported; 110 private final BandDescriptor[] mBands; 111 ModuleProperties(int id, int classId, String implementor, String product, String version, String serial, int numTuners, int numAudioSources, boolean isCaptureSupported, BandDescriptor[] bands)112 ModuleProperties(int id, int classId, String implementor, String product, String version, 113 String serial, int numTuners, int numAudioSources, boolean isCaptureSupported, 114 BandDescriptor[] bands) { 115 mId = id; 116 mClassId = classId; 117 mImplementor = implementor; 118 mProduct = product; 119 mVersion = version; 120 mSerial = serial; 121 mNumTuners = numTuners; 122 mNumAudioSources = numAudioSources; 123 mIsCaptureSupported = isCaptureSupported; 124 mBands = bands; 125 } 126 127 128 /** Unique module identifier provided by the native service. 129 * For use with {@link #openTuner(int, BandConfig, boolean, Callback, Handler)}. 130 * @return the radio module unique identifier. 131 */ getId()132 public int getId() { 133 return mId; 134 } 135 136 /** Module class identifier: {@link #CLASS_AM_FM}, {@link #CLASS_SAT}, {@link #CLASS_DT} 137 * @return the radio module class identifier. 138 */ getClassId()139 public int getClassId() { 140 return mClassId; 141 } 142 143 /** Human readable broadcast radio module implementor 144 * @return the name of the radio module implementator. 145 */ getImplementor()146 public String getImplementor() { 147 return mImplementor; 148 } 149 150 /** Human readable broadcast radio module product name 151 * @return the radio module product name. 152 */ getProduct()153 public String getProduct() { 154 return mProduct; 155 } 156 157 /** Human readable broadcast radio module version number 158 * @return the radio module version. 159 */ getVersion()160 public String getVersion() { 161 return mVersion; 162 } 163 164 /** Radio module serial number. 165 * Can be used for subscription services. 166 * @return the radio module serial number. 167 */ getSerial()168 public String getSerial() { 169 return mSerial; 170 } 171 172 /** Number of tuners available. 173 * This is the number of tuners that can be open simultaneously. 174 * @return the number of tuners supported. 175 */ getNumTuners()176 public int getNumTuners() { 177 return mNumTuners; 178 } 179 180 /** Number tuner audio sources available. Must be less or equal to getNumTuners(). 181 * When more than one tuner is supported, one is usually for playback and has one 182 * associated audio source and the other is for pre scanning and building a 183 * program list. 184 * @return the number of audio sources available. 185 */ getNumAudioSources()186 public int getNumAudioSources() { 187 return mNumAudioSources; 188 } 189 190 /** {@code true} if audio capture is possible from radio tuner output. 191 * This indicates if routing to audio devices not connected to the same HAL as the FM radio 192 * is possible (e.g. to USB) or DAR (Digital Audio Recorder) feature can be implemented. 193 * @return {@code true} if audio capture is possible, {@code false} otherwise. 194 */ isCaptureSupported()195 public boolean isCaptureSupported() { 196 return mIsCaptureSupported; 197 } 198 199 /** List of descriptors for all bands supported by this module. 200 * @return an array of {@link BandDescriptor}. 201 */ getBands()202 public BandDescriptor[] getBands() { 203 return mBands; 204 } 205 ModuleProperties(Parcel in)206 private ModuleProperties(Parcel in) { 207 mId = in.readInt(); 208 mClassId = in.readInt(); 209 mImplementor = in.readString(); 210 mProduct = in.readString(); 211 mVersion = in.readString(); 212 mSerial = in.readString(); 213 mNumTuners = in.readInt(); 214 mNumAudioSources = in.readInt(); 215 mIsCaptureSupported = in.readInt() == 1; 216 Parcelable[] tmp = in.readParcelableArray(BandDescriptor.class.getClassLoader()); 217 mBands = new BandDescriptor[tmp.length]; 218 for (int i = 0; i < tmp.length; i++) { 219 mBands[i] = (BandDescriptor) tmp[i]; 220 } 221 } 222 223 public static final Parcelable.Creator<ModuleProperties> CREATOR 224 = new Parcelable.Creator<ModuleProperties>() { 225 public ModuleProperties createFromParcel(Parcel in) { 226 return new ModuleProperties(in); 227 } 228 229 public ModuleProperties[] newArray(int size) { 230 return new ModuleProperties[size]; 231 } 232 }; 233 234 @Override writeToParcel(Parcel dest, int flags)235 public void writeToParcel(Parcel dest, int flags) { 236 dest.writeInt(mId); 237 dest.writeInt(mClassId); 238 dest.writeString(mImplementor); 239 dest.writeString(mProduct); 240 dest.writeString(mVersion); 241 dest.writeString(mSerial); 242 dest.writeInt(mNumTuners); 243 dest.writeInt(mNumAudioSources); 244 dest.writeInt(mIsCaptureSupported ? 1 : 0); 245 dest.writeParcelableArray(mBands, flags); 246 } 247 248 @Override describeContents()249 public int describeContents() { 250 return 0; 251 } 252 253 @Override toString()254 public String toString() { 255 return "ModuleProperties [mId=" + mId + ", mClassId=" + mClassId 256 + ", mImplementor=" + mImplementor + ", mProduct=" + mProduct 257 + ", mVersion=" + mVersion + ", mSerial=" + mSerial 258 + ", mNumTuners=" + mNumTuners 259 + ", mNumAudioSources=" + mNumAudioSources 260 + ", mIsCaptureSupported=" + mIsCaptureSupported 261 + ", mBands=" + Arrays.toString(mBands) + "]"; 262 } 263 264 @Override hashCode()265 public int hashCode() { 266 final int prime = 31; 267 int result = 1; 268 result = prime * result + mId; 269 result = prime * result + mClassId; 270 result = prime * result + ((mImplementor == null) ? 0 : mImplementor.hashCode()); 271 result = prime * result + ((mProduct == null) ? 0 : mProduct.hashCode()); 272 result = prime * result + ((mVersion == null) ? 0 : mVersion.hashCode()); 273 result = prime * result + ((mSerial == null) ? 0 : mSerial.hashCode()); 274 result = prime * result + mNumTuners; 275 result = prime * result + mNumAudioSources; 276 result = prime * result + (mIsCaptureSupported ? 1 : 0); 277 result = prime * result + Arrays.hashCode(mBands); 278 return result; 279 } 280 281 @Override equals(Object obj)282 public boolean equals(Object obj) { 283 if (this == obj) 284 return true; 285 if (!(obj instanceof ModuleProperties)) 286 return false; 287 ModuleProperties other = (ModuleProperties) obj; 288 if (mId != other.getId()) 289 return false; 290 if (mClassId != other.getClassId()) 291 return false; 292 if (mImplementor == null) { 293 if (other.getImplementor() != null) 294 return false; 295 } else if (!mImplementor.equals(other.getImplementor())) 296 return false; 297 if (mProduct == null) { 298 if (other.getProduct() != null) 299 return false; 300 } else if (!mProduct.equals(other.getProduct())) 301 return false; 302 if (mVersion == null) { 303 if (other.getVersion() != null) 304 return false; 305 } else if (!mVersion.equals(other.getVersion())) 306 return false; 307 if (mSerial == null) { 308 if (other.getSerial() != null) 309 return false; 310 } else if (!mSerial.equals(other.getSerial())) 311 return false; 312 if (mNumTuners != other.getNumTuners()) 313 return false; 314 if (mNumAudioSources != other.getNumAudioSources()) 315 return false; 316 if (mIsCaptureSupported != other.isCaptureSupported()) 317 return false; 318 if (!Arrays.equals(mBands, other.getBands())) 319 return false; 320 return true; 321 } 322 } 323 324 /** Radio band descriptor: an element in ModuleProperties bands array. 325 * It is either an instance of {@link FmBandDescriptor} or {@link AmBandDescriptor} */ 326 public static class BandDescriptor implements Parcelable { 327 328 private final int mRegion; 329 private final int mType; 330 private final int mLowerLimit; 331 private final int mUpperLimit; 332 private final int mSpacing; 333 BandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing)334 BandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing) { 335 mRegion = region; 336 mType = type; 337 mLowerLimit = lowerLimit; 338 mUpperLimit = upperLimit; 339 mSpacing = spacing; 340 } 341 342 /** Region this band applies to. E.g. {@link #REGION_ITU_1} 343 * @return the region this band is associated to. 344 */ getRegion()345 public int getRegion() { 346 return mRegion; 347 } 348 /** Band type, e.g {@link #BAND_FM}. Defines the subclass this descriptor can be cast to: 349 * <ul> 350 * <li>{@link #BAND_FM} or {@link #BAND_FM_HD} cast to {@link FmBandDescriptor}, </li> 351 * <li>{@link #BAND_AM} cast to {@link AmBandDescriptor}, </li> 352 * </ul> 353 * @return the band type. 354 */ getType()355 public int getType() { 356 return mType; 357 } 358 /** Lower band limit expressed in units according to band type. 359 * Currently all defined band types express channels as frequency in kHz 360 * @return the lower band limit. 361 */ getLowerLimit()362 public int getLowerLimit() { 363 return mLowerLimit; 364 } 365 /** Upper band limit expressed in units according to band type. 366 * Currently all defined band types express channels as frequency in kHz 367 * @return the upper band limit. 368 */ getUpperLimit()369 public int getUpperLimit() { 370 return mUpperLimit; 371 } 372 /** Channel spacing in units according to band type. 373 * Currently all defined band types express channels as frequency in kHz 374 * @return the channel spacing. 375 */ getSpacing()376 public int getSpacing() { 377 return mSpacing; 378 } 379 BandDescriptor(Parcel in)380 private BandDescriptor(Parcel in) { 381 mRegion = in.readInt(); 382 mType = in.readInt(); 383 mLowerLimit = in.readInt(); 384 mUpperLimit = in.readInt(); 385 mSpacing = in.readInt(); 386 } 387 388 public static final Parcelable.Creator<BandDescriptor> CREATOR 389 = new Parcelable.Creator<BandDescriptor>() { 390 public BandDescriptor createFromParcel(Parcel in) { 391 return new BandDescriptor(in); 392 } 393 394 public BandDescriptor[] newArray(int size) { 395 return new BandDescriptor[size]; 396 } 397 }; 398 399 @Override writeToParcel(Parcel dest, int flags)400 public void writeToParcel(Parcel dest, int flags) { 401 dest.writeInt(mRegion); 402 dest.writeInt(mType); 403 dest.writeInt(mLowerLimit); 404 dest.writeInt(mUpperLimit); 405 dest.writeInt(mSpacing); 406 } 407 408 @Override describeContents()409 public int describeContents() { 410 return 0; 411 } 412 413 @Override toString()414 public String toString() { 415 return "BandDescriptor [mRegion=" + mRegion + ", mType=" + mType + ", mLowerLimit=" 416 + mLowerLimit + ", mUpperLimit=" + mUpperLimit + ", mSpacing=" + mSpacing + "]"; 417 } 418 419 @Override hashCode()420 public int hashCode() { 421 final int prime = 31; 422 int result = 1; 423 result = prime * result + mRegion; 424 result = prime * result + mType; 425 result = prime * result + mLowerLimit; 426 result = prime * result + mUpperLimit; 427 result = prime * result + mSpacing; 428 return result; 429 } 430 431 @Override equals(Object obj)432 public boolean equals(Object obj) { 433 if (this == obj) 434 return true; 435 if (!(obj instanceof BandDescriptor)) 436 return false; 437 BandDescriptor other = (BandDescriptor) obj; 438 if (mRegion != other.getRegion()) 439 return false; 440 if (mType != other.getType()) 441 return false; 442 if (mLowerLimit != other.getLowerLimit()) 443 return false; 444 if (mUpperLimit != other.getUpperLimit()) 445 return false; 446 if (mSpacing != other.getSpacing()) 447 return false; 448 return true; 449 } 450 } 451 452 /** FM band descriptor 453 * @see #BAND_FM 454 * @see #BAND_FM_HD */ 455 public static class FmBandDescriptor extends BandDescriptor { 456 private final boolean mStereo; 457 private final boolean mRds; 458 private final boolean mTa; 459 private final boolean mAf; 460 private final boolean mEa; 461 FmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo, boolean rds, boolean ta, boolean af, boolean ea)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 */ isStereoSupported()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 */ isRdsSupported()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 */ isTaSupported()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 */ isAfSupported()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 */ isEaSupported()500 public boolean isEaSupported() { 501 return mEa; 502 } 503 504 /* Parcelable implementation */ FmBandDescriptor(Parcel in)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 writeToParcel(Parcel dest, int flags)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 describeContents()536 public int describeContents() { 537 return 0; 538 } 539 540 @Override toString()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 hashCode()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 equals(Object obj)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 AmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo)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 */ isStereoSupported()597 public boolean isStereoSupported() { 598 return mStereo; 599 } 600 AmBandDescriptor(Parcel in)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 writeToParcel(Parcel dest, int flags)618 public void writeToParcel(Parcel dest, int flags) { 619 super.writeToParcel(dest, flags); 620 dest.writeByte((byte) (mStereo ? 1 : 0)); 621 } 622 623 @Override describeContents()624 public int describeContents() { 625 return 0; 626 } 627 628 @Override toString()629 public String toString() { 630 return "AmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo + "]"; 631 } 632 633 @Override hashCode()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 equals(Object obj)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 BandConfig(BandDescriptor descriptor)662 BandConfig(BandDescriptor descriptor) { 663 mDescriptor = descriptor; 664 } 665 BandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing)666 BandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing) { 667 mDescriptor = new BandDescriptor(region, type, lowerLimit, upperLimit, spacing); 668 } 669 BandConfig(Parcel in)670 private BandConfig(Parcel in) { 671 mDescriptor = new BandDescriptor(in); 672 } 673 getDescriptor()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 */ getRegion()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 */ getType()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 */ getLowerLimit()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 */ getUpperLimit()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 */ getSpacing()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 writeToParcel(Parcel dest, int flags)729 public void writeToParcel(Parcel dest, int flags) { 730 mDescriptor.writeToParcel(dest, flags); 731 } 732 733 @Override describeContents()734 public int describeContents() { 735 return 0; 736 } 737 738 @Override toString()739 public String toString() { 740 return "BandConfig [ " + mDescriptor.toString() + "]"; 741 } 742 743 @Override hashCode()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 equals(Object obj)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 FmBandConfig(FmBandDescriptor descriptor)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 FmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo, boolean rds, boolean ta, boolean af, boolean ea)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 */ getStereo()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 */ getRds()803 public boolean getRds() { 804 return mRds; 805 } 806 807 /** Get Traffic announcement enable state 808 * @return the enable state. 809 */ getTa()810 public boolean getTa() { 811 return mTa; 812 } 813 814 /** Get Alternate Frequency Switching enable state 815 * @return the enable state. 816 */ getAf()817 public boolean getAf() { 818 return mAf; 819 } 820 821 /** 822 * Get Emergency announcement enable state 823 * @return the enable state. 824 */ getEa()825 public boolean getEa() { 826 return mEa; 827 } 828 FmBandConfig(Parcel in)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 writeToParcel(Parcel dest, int flags)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 describeContents()860 public int describeContents() { 861 return 0; 862 } 863 864 @Override toString()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 hashCode()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 equals(Object obj)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 */ Builder(FmBandDescriptor descriptor)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 */ Builder(FmBandConfig config)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 */ build()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 */ setStereo(boolean state)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 */ setRds(boolean state)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 */ setTa(boolean state)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 */ setAf(boolean state)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 */ setEa(boolean state)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 AmBandConfig(AmBandDescriptor descriptor)1010 AmBandConfig(AmBandDescriptor descriptor) { 1011 super((BandDescriptor)descriptor); 1012 mStereo = descriptor.isStereoSupported(); 1013 } 1014 AmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo)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 */ getStereo()1024 public boolean getStereo() { 1025 return mStereo; 1026 } 1027 AmBandConfig(Parcel in)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 writeToParcel(Parcel dest, int flags)1045 public void writeToParcel(Parcel dest, int flags) { 1046 super.writeToParcel(dest, flags); 1047 dest.writeByte((byte) (mStereo ? 1 : 0)); 1048 } 1049 1050 @Override describeContents()1051 public int describeContents() { 1052 return 0; 1053 } 1054 1055 @Override toString()1056 public String toString() { 1057 return "AmBandConfig [" + super.toString() 1058 + ", mStereo=" + mStereo + "]"; 1059 } 1060 1061 @Override hashCode()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 equals(Object obj)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 */ Builder(AmBandDescriptor descriptor)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 */ Builder(AmBandConfig config)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 */ build()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 */ setStereo(boolean state)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 ProgramInfo(int channel, int subChannel, boolean tuned, boolean stereo, boolean digital, int signalStrength, RadioMetadata metadata)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 */ getChannel()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 */ getSubChannel()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 */ isTuned()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 */ isStereo()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 */ isDigital()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 */ getSignalStrength()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 */ getMetadata()1199 public RadioMetadata getMetadata() { 1200 return mMetadata; 1201 } 1202 ProgramInfo(Parcel in)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 writeToParcel(Parcel dest, int flags)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 describeContents()1245 public int describeContents() { 1246 return 0; 1247 } 1248 1249 @Override toString()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 hashCode()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 equals(Object obj)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 */ listModules(List <ModuleProperties> modules)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 */ openTuner(int moduleId, BandConfig config, boolean withAudio, RadioTuner.Callback callback, Handler handler)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 */ RadioManager(Context context)1348 public RadioManager(Context context) { 1349 mContext = context; 1350 } 1351 } 1352