Copyright (C) 2015 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
/** * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
package android.hardware.radio; import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; import android.content.pm.PackageManager; import android.os.Handler; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.text.TextUtils; import android.util.Log; import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.Executor; import java.util.stream.Collectors;
The RadioManager class allows to control a broadcast radio tuner present on the device. It provides data structures and methods to query for available radio modules, list their properties and open an interface to control tuning operations and receive callbacks when asynchronous operations complete or events occur.
@hide
/** * The RadioManager class allows to control a broadcast radio tuner present on the device. * It provides data structures and methods to query for available radio modules, list their * properties and open an interface to control tuning operations and receive callbacks when * asynchronous operations complete or events occur. * @hide */
@SystemApi @SystemService(Context.RADIO_SERVICE) @RequiresFeature(PackageManager.FEATURE_BROADCAST_RADIO) public class RadioManager { private static final String TAG = "BroadcastRadio.manager";
Method return status: successful operation
/** Method return status: successful operation */
public static final int STATUS_OK = 0;
Method return status: unspecified error
/** Method return status: unspecified error */
public static final int STATUS_ERROR = Integer.MIN_VALUE;
Method return status: permission denied
/** Method return status: permission denied */
public static final int STATUS_PERMISSION_DENIED = -1;
Method return status: initialization failure
/** Method return status: initialization failure */
public static final int STATUS_NO_INIT = -19;
Method return status: invalid argument provided
/** Method return status: invalid argument provided */
public static final int STATUS_BAD_VALUE = -22;
Method return status: cannot reach service
/** Method return status: cannot reach service */
public static final int STATUS_DEAD_OBJECT = -32;
Method return status: invalid or out of sequence operation
/** Method return status: invalid or out of sequence operation */
public static final int STATUS_INVALID_OPERATION = -38;
Method return status: time out before operation completion
/** Method return status: time out before operation completion */
public static final int STATUS_TIMED_OUT = -110; // keep in sync with radio_class_t in /system/core/incluse/system/radio.h
Radio module class supporting FM (including HD radio) and AM
/** Radio module class supporting FM (including HD radio) and AM */
public static final int CLASS_AM_FM = 0;
Radio module class supporting satellite radio
/** Radio module class supporting satellite radio */
public static final int CLASS_SAT = 1;
Radio module class supporting Digital terrestrial radio
/** Radio module class supporting Digital terrestrial radio */
public static final int CLASS_DT = 2; public static final int BAND_INVALID = -1;
AM radio band (LW/MW/SW).
See Also:
  • BandDescriptor
/** AM radio band (LW/MW/SW). * @see BandDescriptor */
public static final int BAND_AM = 0;
FM radio band.
See Also:
  • BandDescriptor
/** FM radio band. * @see BandDescriptor */
public static final int BAND_FM = 1;
FM HD radio or DRM band.
See Also:
  • BandDescriptor
/** FM HD radio or DRM band. * @see BandDescriptor */
public static final int BAND_FM_HD = 2;
AM HD radio or DRM band.
See Also:
  • BandDescriptor
/** AM HD radio or DRM band. * @see BandDescriptor */
public static final int BAND_AM_HD = 3; @IntDef(prefix = { "BAND_" }, value = { BAND_INVALID, BAND_AM, BAND_FM, BAND_AM_HD, BAND_FM_HD, }) @Retention(RetentionPolicy.SOURCE) public @interface Band {} // keep in sync with radio_region_t in /system/core/incluse/system/radio.h
Africa, Europe.
See Also:
  • BandDescriptor
/** Africa, Europe. * @see BandDescriptor */
public static final int REGION_ITU_1 = 0;
Americas.
See Also:
  • BandDescriptor
/** Americas. * @see BandDescriptor */
public static final int REGION_ITU_2 = 1;
Russia.
See Also:
  • BandDescriptor
/** Russia. * @see BandDescriptor */
public static final int REGION_OIRT = 2;
Japan.
See Also:
  • BandDescriptor
/** Japan. * @see BandDescriptor */
public static final int REGION_JAPAN = 3;
Korea.
See Also:
  • BandDescriptor
/** Korea. * @see BandDescriptor */
public static final int REGION_KOREA = 4;
Forces mono audio stream reception. Analog broadcasts can recover poor reception conditions by jointing stereo channels into one. Mainly for, but not limited to AM/FM.
/** * Forces mono audio stream reception. * * Analog broadcasts can recover poor reception conditions by jointing * stereo channels into one. Mainly for, but not limited to AM/FM. */
public static final int CONFIG_FORCE_MONO = 1;
Forces the analog playback for the supporting radio technology. User may disable digital playback for FM HD Radio or hybrid FM/DAB with this option. This is purely user choice, ie. does not reflect digital- analog handover state managed from the HAL implementation side. Some radio technologies may not support this, ie. DAB.
/** * Forces the analog playback for the supporting radio technology. * * User may disable digital playback for FM HD Radio or hybrid FM/DAB with * this option. This is purely user choice, ie. does not reflect digital- * analog handover state managed from the HAL implementation side. * * Some radio technologies may not support this, ie. DAB. */
public static final int CONFIG_FORCE_ANALOG = 2;
Forces the digital playback for the supporting radio technology. User may disable digital-analog handover that happens with poor reception conditions. With digital forced, the radio will remain silent instead of switching to analog channel if it's available. This is purely user choice, it does not reflect the actual state of handover.
/** * Forces the digital playback for the supporting radio technology. * * User may disable digital-analog handover that happens with poor * reception conditions. With digital forced, the radio will remain silent * instead of switching to analog channel if it's available. This is purely * user choice, it does not reflect the actual state of handover. */
public static final int CONFIG_FORCE_DIGITAL = 3;
RDS Alternative Frequencies. If set and the currently tuned RDS station broadcasts on multiple channels, radio tuner automatically switches to the best available alternative.
/** * RDS Alternative Frequencies. * * If set and the currently tuned RDS station broadcasts on multiple * channels, radio tuner automatically switches to the best available * alternative. */
public static final int CONFIG_RDS_AF = 4;
RDS region-specific program lock-down. Allows user to lock to the current region as they move into the other region.
/** * RDS region-specific program lock-down. * * Allows user to lock to the current region as they move into the * other region. */
public static final int CONFIG_RDS_REG = 5;
Enables DAB-DAB hard- and implicit-linking (the same content).
/** Enables DAB-DAB hard- and implicit-linking (the same content). */
public static final int CONFIG_DAB_DAB_LINKING = 6;
Enables DAB-FM hard- and implicit-linking (the same content).
/** Enables DAB-FM hard- and implicit-linking (the same content). */
public static final int CONFIG_DAB_FM_LINKING = 7;
Enables DAB-DAB soft-linking (related content).
/** Enables DAB-DAB soft-linking (related content). */
public static final int CONFIG_DAB_DAB_SOFT_LINKING = 8;
Enables DAB-FM soft-linking (related content).
/** Enables DAB-FM soft-linking (related content). */
public static final int CONFIG_DAB_FM_SOFT_LINKING = 9;
@hide
/** @hide */
@IntDef(prefix = { "CONFIG_" }, value = { CONFIG_FORCE_MONO, CONFIG_FORCE_ANALOG, CONFIG_FORCE_DIGITAL, CONFIG_RDS_AF, CONFIG_RDS_REG, CONFIG_DAB_DAB_LINKING, CONFIG_DAB_FM_LINKING, CONFIG_DAB_DAB_SOFT_LINKING, CONFIG_DAB_FM_SOFT_LINKING, }) @Retention(RetentionPolicy.SOURCE) public @interface ConfigFlag {}
Lists properties, options and radio bands supported by a given broadcast radio module. Each module has a unique ID used to address it when calling RadioManager APIs. Module properties are returned by #listModules(List <ModuleProperties>) method.
/***************************************************************************** * Lists properties, options and radio bands supported by a given broadcast radio module. * Each module has a unique ID used to address it when calling RadioManager APIs. * Module properties are returned by {@link #listModules(List <ModuleProperties>)} method. ****************************************************************************/
public static class ModuleProperties implements Parcelable { private final int mId; @NonNull private final String mServiceName; private final int mClassId; private final String mImplementor; private final String mProduct; private final String mVersion; private final String mSerial; private final int mNumTuners; private final int mNumAudioSources; private final boolean mIsInitializationRequired; private final boolean mIsCaptureSupported; private final BandDescriptor[] mBands; private final boolean mIsBgScanSupported; private final Set<Integer> mSupportedProgramTypes; private final Set<Integer> mSupportedIdentifierTypes; @Nullable private final Map<String, Integer> mDabFrequencyTable; @NonNull private final Map<String, String> mVendorInfo;
@hide
/** @hide */
public ModuleProperties(int id, String serviceName, int classId, String implementor, String product, String version, String serial, int numTuners, int numAudioSources, boolean isInitializationRequired, boolean isCaptureSupported, BandDescriptor[] bands, boolean isBgScanSupported, @ProgramSelector.ProgramType int[] supportedProgramTypes, @ProgramSelector.IdentifierType int[] supportedIdentifierTypes, @Nullable Map<String, Integer> dabFrequencyTable, Map<String, String> vendorInfo) { mId = id; mServiceName = TextUtils.isEmpty(serviceName) ? "default" : serviceName; mClassId = classId; mImplementor = implementor; mProduct = product; mVersion = version; mSerial = serial; mNumTuners = numTuners; mNumAudioSources = numAudioSources; mIsInitializationRequired = isInitializationRequired; mIsCaptureSupported = isCaptureSupported; mBands = bands; mIsBgScanSupported = isBgScanSupported; mSupportedProgramTypes = arrayToSet(supportedProgramTypes); mSupportedIdentifierTypes = arrayToSet(supportedIdentifierTypes); if (dabFrequencyTable != null) { for (Map.Entry<String, Integer> entry : dabFrequencyTable.entrySet()) { Objects.requireNonNull(entry.getKey()); Objects.requireNonNull(entry.getValue()); } } mDabFrequencyTable = dabFrequencyTable; mVendorInfo = (vendorInfo == null) ? new HashMap<>() : vendorInfo; } private static Set<Integer> arrayToSet(int[] arr) { return Arrays.stream(arr).boxed().collect(Collectors.toSet()); } private static int[] setToArray(Set<Integer> set) { return set.stream().mapToInt(Integer::intValue).toArray(); }
Unique module identifier provided by the native service. For use with openTuner(int, BandConfig, boolean, Callback, Handler).
Returns:the radio module unique identifier.
/** Unique module identifier provided by the native service. * For use with {@link #openTuner(int, BandConfig, boolean, Callback, Handler)}. * @return the radio module unique identifier. */
public int getId() { return mId; }
Module service (driver) name as registered with HIDL.
Returns:the module service name.
/** * Module service (driver) name as registered with HIDL. * @return the module service name. */
public @NonNull String getServiceName() { return mServiceName; }
Returns:the radio module class identifier.
/** Module class identifier: {@link #CLASS_AM_FM}, {@link #CLASS_SAT}, {@link #CLASS_DT} * @return the radio module class identifier. */
public int getClassId() { return mClassId; }
Human readable broadcast radio module implementor
Returns:the name of the radio module implementator.
/** Human readable broadcast radio module implementor * @return the name of the radio module implementator. */
public String getImplementor() { return mImplementor; }
Human readable broadcast radio module product name
Returns:the radio module product name.
/** Human readable broadcast radio module product name * @return the radio module product name. */
public String getProduct() { return mProduct; }
Human readable broadcast radio module version number
Returns:the radio module version.
/** Human readable broadcast radio module version number * @return the radio module version. */
public String getVersion() { return mVersion; }
Radio module serial number. Can be used for subscription services.
Returns:the radio module serial number.
/** Radio module serial number. * Can be used for subscription services. * @return the radio module serial number. */
public String getSerial() { return mSerial; }
Number of tuners available. This is the number of tuners that can be open simultaneously.
Returns:the number of tuners supported.
/** Number of tuners available. * This is the number of tuners that can be open simultaneously. * @return the number of tuners supported. */
public int getNumTuners() { return mNumTuners; }
Number tuner audio sources available. Must be less or equal to getNumTuners(). When more than one tuner is supported, one is usually for playback and has one associated audio source and the other is for pre scanning and building a program list.
Returns:the number of audio sources available.
/** Number tuner audio sources available. Must be less or equal to getNumTuners(). * When more than one tuner is supported, one is usually for playback and has one * associated audio source and the other is for pre scanning and building a * program list. * @return the number of audio sources available. */
public int getNumAudioSources() { return mNumAudioSources; }
Checks, if BandConfig initialization (after RadioManager.openTuner) is required to be done before other operations or not. If it is, the client has to wait for Callback.onConfigurationChanged callback before executing any other operations. Otherwise, such operation will fail returning RadioManager.STATUS_INVALID_OPERATION error code.
/** * Checks, if BandConfig initialization (after {@link RadioManager#openTuner}) * is required to be done before other operations or not. * * If it is, the client has to wait for {@link RadioTuner.Callback#onConfigurationChanged} * callback before executing any other operations. Otherwise, such operation will fail * returning {@link RadioManager#STATUS_INVALID_OPERATION} error code. */
public boolean isInitializationRequired() { return mIsInitializationRequired; }
true if audio capture is possible from radio tuner output. This indicates if routing to audio devices not connected to the same HAL as the FM radio is possible (e.g. to USB) or DAR (Digital Audio Recorder) feature can be implemented.
Returns:true if audio capture is possible, false otherwise.
/** {@code true} if audio capture is possible from radio tuner output. * This indicates if routing to audio devices not connected to the same HAL as the FM radio * is possible (e.g. to USB) or DAR (Digital Audio Recorder) feature can be implemented. * @return {@code true} if audio capture is possible, {@code false} otherwise. */
public boolean isCaptureSupported() { return mIsCaptureSupported; }
true if the module supports background scanning. At the given time it may not be available though, see RadioTuner.startBackgroundScan().
Returns:true if background scanning is supported (not necessary available at a given time), false otherwise.
/** * {@code true} if the module supports background scanning. At the given time it may not * be available though, see {@link RadioTuner#startBackgroundScan()}. * * @return {@code true} if background scanning is supported (not necessary available * at a given time), {@code false} otherwise. */
public boolean isBackgroundScanningSupported() { return mIsBgScanSupported; }
Checks, if a given program type is supported by this tuner. If a program type is supported by radio module, it means it can tune to ProgramSelector of a given type.
Returns:true if a given program type is supported.
/** * Checks, if a given program type is supported by this tuner. * * If a program type is supported by radio module, it means it can tune * to ProgramSelector of a given type. * * @return {@code true} if a given program type is supported. */
public boolean isProgramTypeSupported(@ProgramSelector.ProgramType int type) { return mSupportedProgramTypes.contains(type); }
Checks, if a given program identifier is supported by this tuner. If an identifier is supported by radio module, it means it can use it for tuning to ProgramSelector with either primary or secondary Identifier of a given type.
Returns:true if a given program type is supported.
/** * Checks, if a given program identifier is supported by this tuner. * * If an identifier is supported by radio module, it means it can use it for * tuning to ProgramSelector with either primary or secondary Identifier of * a given type. * * @return {@code true} if a given program type is supported. */
public boolean isProgramIdentifierSupported(@ProgramSelector.IdentifierType int type) { return mSupportedIdentifierTypes.contains(type); }
A frequency table for Digital Audio Broadcasting (DAB). The key is a channel name, i.e. 5A, 7B. The value is a frequency, in kHz.
Returns:a frequency table, or null if the module doesn't support DAB
/** * A frequency table for Digital Audio Broadcasting (DAB). * * The key is a channel name, i.e. 5A, 7B. * * The value is a frequency, in kHz. * * @return a frequency table, or {@code null} if the module doesn't support DAB */
public @Nullable Map<String, Integer> getDabFrequencyTable() { return mDabFrequencyTable; }
A map of vendor-specific opaque strings, passed from HAL without changes. Format of these strings can vary across vendors. It may be used for extra features, that's not supported by a platform, for example: preset-slots=6; ultra-hd-capable=false. Keys must be prefixed with unique vendor Java-style namespace, eg. 'com.somecompany.parameter1'.
/** * A map of vendor-specific opaque strings, passed from HAL without changes. * Format of these strings can vary across vendors. * * It may be used for extra features, that's not supported by a platform, * for example: preset-slots=6; ultra-hd-capable=false. * * Keys must be prefixed with unique vendor Java-style namespace, * eg. 'com.somecompany.parameter1'. */
public @NonNull Map<String, String> getVendorInfo() { return mVendorInfo; }
List of descriptors for all bands supported by this module.
Returns:an array of BandDescriptor.
/** List of descriptors for all bands supported by this module. * @return an array of {@link BandDescriptor}. */
public BandDescriptor[] getBands() { return mBands; } private ModuleProperties(Parcel in) { mId = in.readInt(); String serviceName = in.readString(); mServiceName = TextUtils.isEmpty(serviceName) ? "default" : serviceName; mClassId = in.readInt(); mImplementor = in.readString(); mProduct = in.readString(); mVersion = in.readString(); mSerial = in.readString(); mNumTuners = in.readInt(); mNumAudioSources = in.readInt(); mIsInitializationRequired = in.readInt() == 1; mIsCaptureSupported = in.readInt() == 1; Parcelable[] tmp = in.readParcelableArray(BandDescriptor.class.getClassLoader()); mBands = new BandDescriptor[tmp.length]; for (int i = 0; i < tmp.length; i++) { mBands[i] = (BandDescriptor) tmp[i]; } mIsBgScanSupported = in.readInt() == 1; mSupportedProgramTypes = arrayToSet(in.createIntArray()); mSupportedIdentifierTypes = arrayToSet(in.createIntArray()); mDabFrequencyTable = Utils.readStringIntMap(in); mVendorInfo = Utils.readStringMap(in); } public static final Parcelable.Creator<ModuleProperties> CREATOR = new Parcelable.Creator<ModuleProperties>() { public ModuleProperties createFromParcel(Parcel in) { return new ModuleProperties(in); } public ModuleProperties[] newArray(int size) { return new ModuleProperties[size]; } }; @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mId); dest.writeString(mServiceName); dest.writeInt(mClassId); dest.writeString(mImplementor); dest.writeString(mProduct); dest.writeString(mVersion); dest.writeString(mSerial); dest.writeInt(mNumTuners); dest.writeInt(mNumAudioSources); dest.writeInt(mIsInitializationRequired ? 1 : 0); dest.writeInt(mIsCaptureSupported ? 1 : 0); dest.writeParcelableArray(mBands, flags); dest.writeInt(mIsBgScanSupported ? 1 : 0); dest.writeIntArray(setToArray(mSupportedProgramTypes)); dest.writeIntArray(setToArray(mSupportedIdentifierTypes)); Utils.writeStringIntMap(dest, mDabFrequencyTable); Utils.writeStringMap(dest, mVendorInfo); } @Override public int describeContents() { return 0; } @Override public String toString() { return "ModuleProperties [mId=" + mId + ", mServiceName=" + mServiceName + ", mClassId=" + mClassId + ", mImplementor=" + mImplementor + ", mProduct=" + mProduct + ", mVersion=" + mVersion + ", mSerial=" + mSerial + ", mNumTuners=" + mNumTuners + ", mNumAudioSources=" + mNumAudioSources + ", mIsInitializationRequired=" + mIsInitializationRequired + ", mIsCaptureSupported=" + mIsCaptureSupported + ", mIsBgScanSupported=" + mIsBgScanSupported + ", mBands=" + Arrays.toString(mBands) + "]"; } @Override public int hashCode() { return Objects.hash(mId, mServiceName, mClassId, mImplementor, mProduct, mVersion, mSerial, mNumTuners, mNumAudioSources, mIsInitializationRequired, mIsCaptureSupported, mBands, mIsBgScanSupported, mDabFrequencyTable, mVendorInfo); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof ModuleProperties)) return false; ModuleProperties other = (ModuleProperties) obj; if (mId != other.getId()) return false; if (!TextUtils.equals(mServiceName, other.mServiceName)) return false; if (mClassId != other.mClassId) return false; if (!Objects.equals(mImplementor, other.mImplementor)) return false; if (!Objects.equals(mProduct, other.mProduct)) return false; if (!Objects.equals(mVersion, other.mVersion)) return false; if (!Objects.equals(mSerial, other.mSerial)) return false; if (mNumTuners != other.mNumTuners) return false; if (mNumAudioSources != other.mNumAudioSources) return false; if (mIsInitializationRequired != other.mIsInitializationRequired) return false; if (mIsCaptureSupported != other.mIsCaptureSupported) return false; if (!Objects.equals(mBands, other.mBands)) return false; if (mIsBgScanSupported != other.mIsBgScanSupported) return false; if (!Objects.equals(mDabFrequencyTable, other.mDabFrequencyTable)) return false; if (!Objects.equals(mVendorInfo, other.mVendorInfo)) return false; return true; } }
Radio band descriptor: an element in ModuleProperties bands array. It is either an instance of FmBandDescriptor or AmBandDescriptor
/** Radio band descriptor: an element in ModuleProperties bands array. * It is either an instance of {@link FmBandDescriptor} or {@link AmBandDescriptor} */
public static class BandDescriptor implements Parcelable { private final int mRegion; private final int mType; private final int mLowerLimit; private final int mUpperLimit; private final int mSpacing; BandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing) { if (type != BAND_AM && type != BAND_FM && type != BAND_FM_HD && type != BAND_AM_HD) { throw new IllegalArgumentException("Unsupported band: " + type); } mRegion = region; mType = type; mLowerLimit = lowerLimit; mUpperLimit = upperLimit; mSpacing = spacing; }
Region this band applies to. E.g. RadioManager.REGION_ITU_1
Returns:the region this band is associated to.
/** Region this band applies to. E.g. {@link #REGION_ITU_1} * @return the region this band is associated to. */
public int getRegion() { return mRegion; }
Band type, e.g RadioManager.BAND_FM. Defines the subclass this descriptor can be cast to:
Returns:the band type.
/** Band type, e.g {@link #BAND_FM}. Defines the subclass this descriptor can be cast to: * <ul> * <li>{@link #BAND_FM} or {@link #BAND_FM_HD} cast to {@link FmBandDescriptor}, </li> * <li>{@link #BAND_AM} cast to {@link AmBandDescriptor}, </li> * </ul> * @return the band type. */
public int getType() { return mType; }
Checks if the band is either AM or AM_HD.
Returns:true, if band is AM or AM_HD.
/** * Checks if the band is either AM or AM_HD. * * @return {@code true}, if band is AM or AM_HD. */
public boolean isAmBand() { return mType == BAND_AM || mType == BAND_AM_HD; }
Checks if the band is either FM or FM_HD.
Returns:true, if band is FM or FM_HD.
/** * Checks if the band is either FM or FM_HD. * * @return {@code true}, if band is FM or FM_HD. */
public boolean isFmBand() { return mType == BAND_FM || mType == BAND_FM_HD; }
Lower band limit expressed in units according to band type. Currently all defined band types express channels as frequency in kHz
Returns:the lower band limit.
/** Lower band limit expressed in units according to band type. * Currently all defined band types express channels as frequency in kHz * @return the lower band limit. */
public int getLowerLimit() { return mLowerLimit; }
Upper band limit expressed in units according to band type. Currently all defined band types express channels as frequency in kHz
Returns:the upper band limit.
/** Upper band limit expressed in units according to band type. * Currently all defined band types express channels as frequency in kHz * @return the upper band limit. */
public int getUpperLimit() { return mUpperLimit; }
Channel spacing in units according to band type. Currently all defined band types express channels as frequency in kHz
Returns:the channel spacing.
/** Channel spacing in units according to band type. * Currently all defined band types express channels as frequency in kHz * @return the channel spacing. */
public int getSpacing() { return mSpacing; } private BandDescriptor(Parcel in) { mRegion = in.readInt(); mType = in.readInt(); mLowerLimit = in.readInt(); mUpperLimit = in.readInt(); mSpacing = in.readInt(); } private static int lookupTypeFromParcel(Parcel in) { int pos = in.dataPosition(); in.readInt(); // skip region int type = in.readInt(); in.setDataPosition(pos); return type; } public static final Parcelable.Creator<BandDescriptor> CREATOR = new Parcelable.Creator<BandDescriptor>() { public BandDescriptor createFromParcel(Parcel in) { int type = lookupTypeFromParcel(in); switch (type) { case BAND_FM: case BAND_FM_HD: return new FmBandDescriptor(in); case BAND_AM: case BAND_AM_HD: return new AmBandDescriptor(in); default: throw new IllegalArgumentException("Unsupported band: " + type); } } public BandDescriptor[] newArray(int size) { return new BandDescriptor[size]; } }; @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mRegion); dest.writeInt(mType); dest.writeInt(mLowerLimit); dest.writeInt(mUpperLimit); dest.writeInt(mSpacing); } @Override public int describeContents() { return 0; } @Override public String toString() { return "BandDescriptor [mRegion=" + mRegion + ", mType=" + mType + ", mLowerLimit=" + mLowerLimit + ", mUpperLimit=" + mUpperLimit + ", mSpacing=" + mSpacing + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + mRegion; result = prime * result + mType; result = prime * result + mLowerLimit; result = prime * result + mUpperLimit; result = prime * result + mSpacing; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof BandDescriptor)) return false; BandDescriptor other = (BandDescriptor) obj; if (mRegion != other.getRegion()) return false; if (mType != other.getType()) return false; if (mLowerLimit != other.getLowerLimit()) return false; if (mUpperLimit != other.getUpperLimit()) return false; if (mSpacing != other.getSpacing()) return false; return true; } }
FM band descriptor
See Also:
/** FM band descriptor * @see #BAND_FM * @see #BAND_FM_HD */
public static class FmBandDescriptor extends BandDescriptor { private final boolean mStereo; private final boolean mRds; private final boolean mTa; private final boolean mAf; private final boolean mEa;
@hide
/** @hide */
public FmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo, boolean rds, boolean ta, boolean af, boolean ea) { super(region, type, lowerLimit, upperLimit, spacing); mStereo = stereo; mRds = rds; mTa = ta; mAf = af; mEa = ea; }
Stereo is supported
Returns:true if stereo is supported, false otherwise.
/** Stereo is supported * @return {@code true} if stereo is supported, {@code false} otherwise. */
public boolean isStereoSupported() { return mStereo; }
RDS or RBDS(if region is ITU2) is supported
Returns:true if RDS or RBDS is supported, false otherwise.
/** RDS or RBDS(if region is ITU2) is supported * @return {@code true} if RDS or RBDS is supported, {@code false} otherwise. */
public boolean isRdsSupported() { return mRds; }
Traffic announcement is supported
Returns:true if TA is supported, false otherwise.
/** Traffic announcement is supported * @return {@code true} if TA is supported, {@code false} otherwise. */
public boolean isTaSupported() { return mTa; }
Alternate Frequency Switching is supported
Returns:true if AF switching is supported, false otherwise.
/** Alternate Frequency Switching is supported * @return {@code true} if AF switching is supported, {@code false} otherwise. */
public boolean isAfSupported() { return mAf; }
Emergency Announcement is supported
Returns:true if Emergency annoucement is supported, false otherwise.
/** Emergency Announcement is supported * @return {@code true} if Emergency annoucement is supported, {@code false} otherwise. */
public boolean isEaSupported() { return mEa; } /* Parcelable implementation */ private FmBandDescriptor(Parcel in) { super(in); mStereo = in.readByte() == 1; mRds = in.readByte() == 1; mTa = in.readByte() == 1; mAf = in.readByte() == 1; mEa = in.readByte() == 1; } public static final Parcelable.Creator<FmBandDescriptor> CREATOR = new Parcelable.Creator<FmBandDescriptor>() { public FmBandDescriptor createFromParcel(Parcel in) { return new FmBandDescriptor(in); } public FmBandDescriptor[] newArray(int size) { return new FmBandDescriptor[size]; } }; @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeByte((byte) (mStereo ? 1 : 0)); dest.writeByte((byte) (mRds ? 1 : 0)); dest.writeByte((byte) (mTa ? 1 : 0)); dest.writeByte((byte) (mAf ? 1 : 0)); dest.writeByte((byte) (mEa ? 1 : 0)); } @Override public int describeContents() { return 0; } @Override public String toString() { return "FmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo + ", mRds=" + mRds + ", mTa=" + mTa + ", mAf=" + mAf + ", mEa =" + mEa + "]"; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + (mStereo ? 1 : 0); result = prime * result + (mRds ? 1 : 0); result = prime * result + (mTa ? 1 : 0); result = prime * result + (mAf ? 1 : 0); result = prime * result + (mEa ? 1 : 0); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (!(obj instanceof FmBandDescriptor)) return false; FmBandDescriptor other = (FmBandDescriptor) obj; if (mStereo != other.isStereoSupported()) return false; if (mRds != other.isRdsSupported()) return false; if (mTa != other.isTaSupported()) return false; if (mAf != other.isAfSupported()) return false; if (mEa != other.isEaSupported()) return false; return true; } }
AM band descriptor.
See Also:
  • BAND_AM
/** AM band descriptor. * @see #BAND_AM */
public static class AmBandDescriptor extends BandDescriptor { private final boolean mStereo;
@hide
/** @hide */
public AmBandDescriptor(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo) { super(region, type, lowerLimit, upperLimit, spacing); mStereo = stereo; }
Stereo is supported @return true if stereo is supported, false otherwise.
/** Stereo is supported * @return {@code true} if stereo is supported, {@code false} otherwise. */
public boolean isStereoSupported() { return mStereo; } private AmBandDescriptor(Parcel in) { super(in); mStereo = in.readByte() == 1; } public static final Parcelable.Creator<AmBandDescriptor> CREATOR = new Parcelable.Creator<AmBandDescriptor>() { public AmBandDescriptor createFromParcel(Parcel in) { return new AmBandDescriptor(in); } public AmBandDescriptor[] newArray(int size) { return new AmBandDescriptor[size]; } }; @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeByte((byte) (mStereo ? 1 : 0)); } @Override public int describeContents() { return 0; } @Override public String toString() { return "AmBandDescriptor [ "+ super.toString() + " mStereo=" + mStereo + "]"; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + (mStereo ? 1 : 0); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (!(obj instanceof AmBandDescriptor)) return false; AmBandDescriptor other = (AmBandDescriptor) obj; if (mStereo != other.isStereoSupported()) return false; return true; } }
Radio band configuration.
/** Radio band configuration. */
public static class BandConfig implements Parcelable { @NonNull final BandDescriptor mDescriptor; BandConfig(BandDescriptor descriptor) { mDescriptor = Objects.requireNonNull(descriptor); } BandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing) { mDescriptor = new BandDescriptor(region, type, lowerLimit, upperLimit, spacing); } private BandConfig(Parcel in) { mDescriptor = new BandDescriptor(in); } BandDescriptor getDescriptor() { return mDescriptor; }
Region this band applies to. E.g. RadioManager.REGION_ITU_1 @return the region associated with this band.
/** Region this band applies to. E.g. {@link #REGION_ITU_1} * @return the region associated with this band. */
public int getRegion() { return mDescriptor.getRegion(); }
Band type, e.g RadioManager.BAND_FM. Defines the subclass this descriptor can be cast to: @return the band type.
/** Band type, e.g {@link #BAND_FM}. Defines the subclass this descriptor can be cast to: * <ul> * <li>{@link #BAND_FM} or {@link #BAND_FM_HD} cast to {@link FmBandDescriptor}, </li> * <li>{@link #BAND_AM} cast to {@link AmBandDescriptor}, </li> * </ul> * @return the band type. */
public int getType() { return mDescriptor.getType(); }
Lower band limit expressed in units according to band type. Currently all defined band types express channels as frequency in kHz @return the lower band limit.
/** Lower band limit expressed in units according to band type. * Currently all defined band types express channels as frequency in kHz * @return the lower band limit. */
public int getLowerLimit() { return mDescriptor.getLowerLimit(); }
Upper band limit expressed in units according to band type. Currently all defined band types express channels as frequency in kHz @return the upper band limit.
/** Upper band limit expressed in units according to band type. * Currently all defined band types express channels as frequency in kHz * @return the upper band limit. */
public int getUpperLimit() { return mDescriptor.getUpperLimit(); }
Channel spacing in units according to band type. Currently all defined band types express channels as frequency in kHz @return the channel spacing.
/** Channel spacing in units according to band type. * Currently all defined band types express channels as frequency in kHz * @return the channel spacing. */
public int getSpacing() { return mDescriptor.getSpacing(); } public static final Parcelable.Creator<BandConfig> CREATOR = new Parcelable.Creator<BandConfig>() { public BandConfig createFromParcel(Parcel in) { int type = BandDescriptor.lookupTypeFromParcel(in); switch (type) { case BAND_FM: case BAND_FM_HD: return new FmBandConfig(in); case BAND_AM: case BAND_AM_HD: return new AmBandConfig(in); default: throw new IllegalArgumentException("Unsupported band: " + type); } } public BandConfig[] newArray(int size) { return new BandConfig[size]; } }; @Override public void writeToParcel(Parcel dest, int flags) { mDescriptor.writeToParcel(dest, flags); } @Override public int describeContents() { return 0; } @Override public String toString() { return "BandConfig [ " + mDescriptor.toString() + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + mDescriptor.hashCode(); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof BandConfig)) return false; BandConfig other = (BandConfig) obj; BandDescriptor otherDesc = other.getDescriptor(); if ((mDescriptor == null) != (otherDesc == null)) return false; if (mDescriptor != null && !mDescriptor.equals(otherDesc)) return false; return true; } }
FM band configuration.
See Also:
/** FM band configuration. * @see #BAND_FM * @see #BAND_FM_HD */
public static class FmBandConfig extends BandConfig { private final boolean mStereo; private final boolean mRds; private final boolean mTa; private final boolean mAf; private final boolean mEa;
@hide
/** @hide */
public FmBandConfig(FmBandDescriptor descriptor) { super((BandDescriptor)descriptor); mStereo = descriptor.isStereoSupported(); mRds = descriptor.isRdsSupported(); mTa = descriptor.isTaSupported(); mAf = descriptor.isAfSupported(); mEa = descriptor.isEaSupported(); } FmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo, boolean rds, boolean ta, boolean af, boolean ea) { super(region, type, lowerLimit, upperLimit, spacing); mStereo = stereo; mRds = rds; mTa = ta; mAf = af; mEa = ea; }
Get stereo enable state
Returns:the enable state.
/** Get stereo enable state * @return the enable state. */
public boolean getStereo() { return mStereo; }
Get RDS or RBDS(if region is ITU2) enable state
Returns:the enable state.
/** Get RDS or RBDS(if region is ITU2) enable state * @return the enable state. */
public boolean getRds() { return mRds; }
Get Traffic announcement enable state
Returns:the enable state.
/** Get Traffic announcement enable state * @return the enable state. */
public boolean getTa() { return mTa; }
Get Alternate Frequency Switching enable state
Returns:the enable state.
/** Get Alternate Frequency Switching enable state * @return the enable state. */
public boolean getAf() { return mAf; }
Get Emergency announcement enable state
Returns:the enable state.
/** * Get Emergency announcement enable state * @return the enable state. */
public boolean getEa() { return mEa; } private FmBandConfig(Parcel in) { super(in); mStereo = in.readByte() == 1; mRds = in.readByte() == 1; mTa = in.readByte() == 1; mAf = in.readByte() == 1; mEa = in.readByte() == 1; } public static final Parcelable.Creator<FmBandConfig> CREATOR = new Parcelable.Creator<FmBandConfig>() { public FmBandConfig createFromParcel(Parcel in) { return new FmBandConfig(in); } public FmBandConfig[] newArray(int size) { return new FmBandConfig[size]; } }; @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeByte((byte) (mStereo ? 1 : 0)); dest.writeByte((byte) (mRds ? 1 : 0)); dest.writeByte((byte) (mTa ? 1 : 0)); dest.writeByte((byte) (mAf ? 1 : 0)); dest.writeByte((byte) (mEa ? 1 : 0)); } @Override public int describeContents() { return 0; } @Override public String toString() { return "FmBandConfig [" + super.toString() + ", mStereo=" + mStereo + ", mRds=" + mRds + ", mTa=" + mTa + ", mAf=" + mAf + ", mEa =" + mEa + "]"; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + (mStereo ? 1 : 0); result = prime * result + (mRds ? 1 : 0); result = prime * result + (mTa ? 1 : 0); result = prime * result + (mAf ? 1 : 0); result = prime * result + (mEa ? 1 : 0); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (!(obj instanceof FmBandConfig)) return false; FmBandConfig other = (FmBandConfig) obj; if (mStereo != other.mStereo) return false; if (mRds != other.mRds) return false; if (mTa != other.mTa) return false; if (mAf != other.mAf) return false; if (mEa != other.mEa) return false; return true; }
Builder class for FmBandConfig objects.
/** * Builder class for {@link FmBandConfig} objects. */
public static class Builder { private final BandDescriptor mDescriptor; private boolean mStereo; private boolean mRds; private boolean mTa; private boolean mAf; private boolean mEa;
Constructs a new Builder with the defaults from an FmBandDescriptor .
Params:
  • descriptor – the FmBandDescriptor defaults are read from .
/** * Constructs a new Builder with the defaults from an {@link FmBandDescriptor} . * @param descriptor the FmBandDescriptor defaults are read from . */
public Builder(FmBandDescriptor descriptor) { mDescriptor = new BandDescriptor(descriptor.getRegion(), descriptor.getType(), descriptor.getLowerLimit(), descriptor.getUpperLimit(), descriptor.getSpacing()); mStereo = descriptor.isStereoSupported(); mRds = descriptor.isRdsSupported(); mTa = descriptor.isTaSupported(); mAf = descriptor.isAfSupported(); mEa = descriptor.isEaSupported(); }
Constructs a new Builder from a given FmBandConfig
Params:
  • config – the FmBandConfig object whose data will be reused in the new Builder.
/** * Constructs a new Builder from a given {@link FmBandConfig} * @param config the FmBandConfig object whose data will be reused in the new Builder. */
public Builder(FmBandConfig config) { mDescriptor = new BandDescriptor(config.getRegion(), config.getType(), config.getLowerLimit(), config.getUpperLimit(), config.getSpacing()); mStereo = config.getStereo(); mRds = config.getRds(); mTa = config.getTa(); mAf = config.getAf(); mEa = config.getEa(); }
Combines all of the parameters that have been set and return a new FmBandConfig object.
Returns:a new FmBandConfig object
/** * Combines all of the parameters that have been set and return a new * {@link FmBandConfig} object. * @return a new {@link FmBandConfig} object */
public FmBandConfig build() { FmBandConfig config = new FmBandConfig(mDescriptor.getRegion(), mDescriptor.getType(), mDescriptor.getLowerLimit(), mDescriptor.getUpperLimit(), mDescriptor.getSpacing(), mStereo, mRds, mTa, mAf, mEa); return config; }
Set stereo enable state
Params:
  • state – The new enable state.
Returns:the same Builder instance.
/** Set stereo enable state * @param state The new enable state. * @return the same Builder instance. */
public Builder setStereo(boolean state) { mStereo = state; return this; }
Set RDS or RBDS(if region is ITU2) enable state
Params:
  • state – The new enable state.
Returns:the same Builder instance.
/** Set RDS or RBDS(if region is ITU2) enable state * @param state The new enable state. * @return the same Builder instance. */
public Builder setRds(boolean state) { mRds = state; return this; }
Set Traffic announcement enable state
Params:
  • state – The new enable state.
Returns:the same Builder instance.
/** Set Traffic announcement enable state * @param state The new enable state. * @return the same Builder instance. */
public Builder setTa(boolean state) { mTa = state; return this; }
Set Alternate Frequency Switching enable state
Params:
  • state – The new enable state.
Returns:the same Builder instance.
/** Set Alternate Frequency Switching enable state * @param state The new enable state. * @return the same Builder instance. */
public Builder setAf(boolean state) { mAf = state; return this; }
Set Emergency Announcement enable state
Params:
  • state – The new enable state.
Returns:the same Builder instance.
/** Set Emergency Announcement enable state * @param state The new enable state. * @return the same Builder instance. */
public Builder setEa(boolean state) { mEa = state; return this; } }; }
AM band configuration.
See Also:
  • BAND_AM
/** AM band configuration. * @see #BAND_AM */
public static class AmBandConfig extends BandConfig { private final boolean mStereo;
@hide
/** @hide */
public AmBandConfig(AmBandDescriptor descriptor) { super((BandDescriptor)descriptor); mStereo = descriptor.isStereoSupported(); } AmBandConfig(int region, int type, int lowerLimit, int upperLimit, int spacing, boolean stereo) { super(region, type, lowerLimit, upperLimit, spacing); mStereo = stereo; }
Get stereo enable state
Returns:the enable state.
/** Get stereo enable state * @return the enable state. */
public boolean getStereo() { return mStereo; } private AmBandConfig(Parcel in) { super(in); mStereo = in.readByte() == 1; } public static final Parcelable.Creator<AmBandConfig> CREATOR = new Parcelable.Creator<AmBandConfig>() { public AmBandConfig createFromParcel(Parcel in) { return new AmBandConfig(in); } public AmBandConfig[] newArray(int size) { return new AmBandConfig[size]; } }; @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeByte((byte) (mStereo ? 1 : 0)); } @Override public int describeContents() { return 0; } @Override public String toString() { return "AmBandConfig [" + super.toString() + ", mStereo=" + mStereo + "]"; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + (mStereo ? 1 : 0); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (!(obj instanceof AmBandConfig)) return false; AmBandConfig other = (AmBandConfig) obj; if (mStereo != other.getStereo()) return false; return true; }
Builder class for AmBandConfig objects.
/** * Builder class for {@link AmBandConfig} objects. */
public static class Builder { private final BandDescriptor mDescriptor; private boolean mStereo;
Constructs a new Builder with the defaults from an AmBandDescriptor .
Params:
  • descriptor – the FmBandDescriptor defaults are read from .
/** * Constructs a new Builder with the defaults from an {@link AmBandDescriptor} . * @param descriptor the FmBandDescriptor defaults are read from . */
public Builder(AmBandDescriptor descriptor) { mDescriptor = new BandDescriptor(descriptor.getRegion(), descriptor.getType(), descriptor.getLowerLimit(), descriptor.getUpperLimit(), descriptor.getSpacing()); mStereo = descriptor.isStereoSupported(); }
Constructs a new Builder from a given AmBandConfig
Params:
  • config – the FmBandConfig object whose data will be reused in the new Builder.
/** * Constructs a new Builder from a given {@link AmBandConfig} * @param config the FmBandConfig object whose data will be reused in the new Builder. */
public Builder(AmBandConfig config) { mDescriptor = new BandDescriptor(config.getRegion(), config.getType(), config.getLowerLimit(), config.getUpperLimit(), config.getSpacing()); mStereo = config.getStereo(); }
Combines all of the parameters that have been set and return a new AmBandConfig object.
Returns:a new AmBandConfig object
/** * Combines all of the parameters that have been set and return a new * {@link AmBandConfig} object. * @return a new {@link AmBandConfig} object */
public AmBandConfig build() { AmBandConfig config = new AmBandConfig(mDescriptor.getRegion(), mDescriptor.getType(), mDescriptor.getLowerLimit(), mDescriptor.getUpperLimit(), mDescriptor.getSpacing(), mStereo); return config; }
Set stereo enable state
Params:
  • state – The new enable state.
Returns:the same Builder instance.
/** Set stereo enable state * @param state The new enable state. * @return the same Builder instance. */
public Builder setStereo(boolean state) { mStereo = state; return this; } }; }
Radio program information.
/** Radio program information. */
public static class ProgramInfo implements Parcelable { // sourced from hardware/interfaces/broadcastradio/2.0/types.hal private static final int FLAG_LIVE = 1 << 0; private static final int FLAG_MUTED = 1 << 1; private static final int FLAG_TRAFFIC_PROGRAM = 1 << 2; private static final int FLAG_TRAFFIC_ANNOUNCEMENT = 1 << 3; private static final int FLAG_TUNED = 1 << 4; private static final int FLAG_STEREO = 1 << 5; @NonNull private final ProgramSelector mSelector; @Nullable private final ProgramSelector.Identifier mLogicallyTunedTo; @Nullable private final ProgramSelector.Identifier mPhysicallyTunedTo; @NonNull private final Collection<ProgramSelector.Identifier> mRelatedContent; private final int mInfoFlags; private final int mSignalQuality; @Nullable private final RadioMetadata mMetadata; @NonNull private final Map<String, String> mVendorInfo;
@hide
/** @hide */
public ProgramInfo(@NonNull ProgramSelector selector, @Nullable ProgramSelector.Identifier logicallyTunedTo, @Nullable ProgramSelector.Identifier physicallyTunedTo, @Nullable Collection<ProgramSelector.Identifier> relatedContent, int infoFlags, int signalQuality, @Nullable RadioMetadata metadata, @Nullable Map<String, String> vendorInfo) { mSelector = Objects.requireNonNull(selector); mLogicallyTunedTo = logicallyTunedTo; mPhysicallyTunedTo = physicallyTunedTo; if (relatedContent == null) { mRelatedContent = Collections.emptyList(); } else { Preconditions.checkCollectionElementsNotNull(relatedContent, "relatedContent"); mRelatedContent = relatedContent; } mInfoFlags = infoFlags; mSignalQuality = signalQuality; mMetadata = metadata; mVendorInfo = (vendorInfo == null) ? new HashMap<>() : vendorInfo; }
Program selector, necessary for tuning to a program.
Returns:the program selector.
/** * Program selector, necessary for tuning to a program. * * @return the program selector. */
public @NonNull ProgramSelector getSelector() { return mSelector; }
Identifier currently used for program selection. This identifier can be used to determine which technology is currently being used for reception. Some program selectors contain tuning information for different radio technologies (i.e. FM RDS and DAB). For example, user may tune using a ProgramSelector with RDS_PI primary identifier, but the tuner hardware may choose to use DAB technology to make actual tuning. This identifier must reflect that.
/** * Identifier currently used for program selection. * * This identifier can be used to determine which technology is * currently being used for reception. * * Some program selectors contain tuning information for different radio * technologies (i.e. FM RDS and DAB). For example, user may tune using * a ProgramSelector with RDS_PI primary identifier, but the tuner hardware * may choose to use DAB technology to make actual tuning. This identifier * must reflect that. */
public @Nullable ProgramSelector.Identifier getLogicallyTunedTo() { return mLogicallyTunedTo; }
Identifier currently used by hardware to physically tune to a channel. Some radio technologies broadcast the same program on multiple channels, i.e. with RDS AF the same program may be broadcasted on multiple alternative frequencies; the same DAB program may be broadcast on multiple ensembles. This identifier points to the channel to which the radio hardware is physically tuned to.
/** * Identifier currently used by hardware to physically tune to a channel. * * Some radio technologies broadcast the same program on multiple channels, * i.e. with RDS AF the same program may be broadcasted on multiple * alternative frequencies; the same DAB program may be broadcast on * multiple ensembles. This identifier points to the channel to which the * radio hardware is physically tuned to. */
public @Nullable ProgramSelector.Identifier getPhysicallyTunedTo() { return mPhysicallyTunedTo; }
Primary identifiers of related contents. Some radio technologies provide pointers to other programs that carry related content (i.e. DAB soft-links). This field is a list of pointers to other programs on the program list. Please note, that these identifiers does not have to exist on the program list - i.e. DAB tuner may provide information on FM RDS alternatives despite not supporting FM RDS. If the system has multiple tuners, another one may have it on its list.
/** * Primary identifiers of related contents. * * Some radio technologies provide pointers to other programs that carry * related content (i.e. DAB soft-links). This field is a list of pointers * to other programs on the program list. * * Please note, that these identifiers does not have to exist on the program * list - i.e. DAB tuner may provide information on FM RDS alternatives * despite not supporting FM RDS. If the system has multiple tuners, another * one may have it on its list. */
public @Nullable Collection<ProgramSelector.Identifier> getRelatedContent() { return mRelatedContent; }
Main channel expressed in units according to band type. Currently all defined band types express channels as frequency in kHz
Returns:the program channel
Deprecated:Use getSelector() instead.
/** Main channel expressed in units according to band type. * Currently all defined band types express channels as frequency in kHz * @return the program channel * @deprecated Use {@link getSelector()} instead. */
@Deprecated public int getChannel() { try { return (int) mSelector.getFirstId(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY); } catch (IllegalArgumentException ex) { Log.w(TAG, "Not an AM/FM program"); return 0; } }
Sub channel ID. E.g 1 for HD radio HD1
Returns:the program sub channel
Deprecated:Use getSelector() instead.
/** Sub channel ID. E.g 1 for HD radio HD1 * @return the program sub channel * @deprecated Use {@link getSelector()} instead. */
@Deprecated public int getSubChannel() { try { return (int) mSelector.getFirstId( ProgramSelector.IDENTIFIER_TYPE_HD_SUBCHANNEL) + 1; } catch (IllegalArgumentException ex) { // this is a normal behavior for analog AM/FM selector return 0; } }
true if the tuner is currently tuned on a valid station
Returns:true if currently tuned, false otherwise.
/** {@code true} if the tuner is currently tuned on a valid station * @return {@code true} if currently tuned, {@code false} otherwise. */
public boolean isTuned() { return (mInfoFlags & FLAG_TUNED) != 0; }
true if the received program is stereo
Returns:true if stereo, false otherwise.
/** {@code true} if the received program is stereo * @return {@code true} if stereo, {@code false} otherwise. */
public boolean isStereo() { return (mInfoFlags & FLAG_STEREO) != 0; }
true if the received program is digital (e.g HD radio)
Returns:true if digital, false otherwise.
Deprecated:Use getLogicallyTunedTo() instead.
/** {@code true} if the received program is digital (e.g HD radio) * @return {@code true} if digital, {@code false} otherwise. * @deprecated Use {@link getLogicallyTunedTo()} instead. */
@Deprecated public boolean isDigital() { ProgramSelector.Identifier id = mLogicallyTunedTo; if (id == null) id = mSelector.getPrimaryId(); int type = id.getType(); return (type != ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY && type != ProgramSelector.IDENTIFIER_TYPE_RDS_PI); }
true if the program is currently playing live stream. This may result in a slightly altered reception parameters, usually targetted at reduced latency.
/** * {@code true} if the program is currently playing live stream. * This may result in a slightly altered reception parameters, * usually targetted at reduced latency. */
public boolean isLive() { return (mInfoFlags & FLAG_LIVE) != 0; }
true if radio stream is not playing, ie. due to bad reception conditions or buffering. In this state volume knob MAY be disabled to prevent user increasing volume too much. It does NOT mean the user has muted audio.
/** * {@code true} if radio stream is not playing, ie. due to bad reception * conditions or buffering. In this state volume knob MAY be disabled to * prevent user increasing volume too much. * It does NOT mean the user has muted audio. */
public boolean isMuted() { return (mInfoFlags & FLAG_MUTED) != 0; }
true if radio station transmits traffic information regularily.
/** * {@code true} if radio station transmits traffic information * regularily. */
public boolean isTrafficProgram() { return (mInfoFlags & FLAG_TRAFFIC_PROGRAM) != 0; }
true if radio station transmits traffic information at the very moment.
/** * {@code true} if radio station transmits traffic information * at the very moment. */
public boolean isTrafficAnnouncementActive() { return (mInfoFlags & FLAG_TRAFFIC_ANNOUNCEMENT) != 0; }
Signal quality (as opposed to the name) indication from 0 (no signal) to 100 (excellent)
Returns:the signal quality indication.
/** * Signal quality (as opposed to the name) indication from 0 (no signal) * to 100 (excellent) * @return the signal quality indication. */
public int getSignalStrength() { return mSignalQuality; }
Metadata currently received from this station. null if no metadata have been received
Returns:current meta data received from this program.
/** Metadata currently received from this station. * null if no metadata have been received * @return current meta data received from this program. */
public RadioMetadata getMetadata() { return mMetadata; }
A map of vendor-specific opaque strings, passed from HAL without changes. Format of these strings can vary across vendors. It may be used for extra features, that's not supported by a platform, for example: paid-service=true; bitrate=320kbps. Keys must be prefixed with unique vendor Java-style namespace, eg. 'com.somecompany.parameter1'.
/** * A map of vendor-specific opaque strings, passed from HAL without changes. * Format of these strings can vary across vendors. * * It may be used for extra features, that's not supported by a platform, * for example: paid-service=true; bitrate=320kbps. * * Keys must be prefixed with unique vendor Java-style namespace, * eg. 'com.somecompany.parameter1'. */
public @NonNull Map<String, String> getVendorInfo() { return mVendorInfo; } private ProgramInfo(Parcel in) { mSelector = Objects.requireNonNull(in.readTypedObject(ProgramSelector.CREATOR)); mLogicallyTunedTo = in.readTypedObject(ProgramSelector.Identifier.CREATOR); mPhysicallyTunedTo = in.readTypedObject(ProgramSelector.Identifier.CREATOR); mRelatedContent = in.createTypedArrayList(ProgramSelector.Identifier.CREATOR); mInfoFlags = in.readInt(); mSignalQuality = in.readInt(); mMetadata = in.readTypedObject(RadioMetadata.CREATOR); mVendorInfo = Utils.readStringMap(in); } public static final Parcelable.Creator<ProgramInfo> CREATOR = new Parcelable.Creator<ProgramInfo>() { public ProgramInfo createFromParcel(Parcel in) { return new ProgramInfo(in); } public ProgramInfo[] newArray(int size) { return new ProgramInfo[size]; } }; @Override public void writeToParcel(Parcel dest, int flags) { dest.writeTypedObject(mSelector, flags); dest.writeTypedObject(mLogicallyTunedTo, flags); dest.writeTypedObject(mPhysicallyTunedTo, flags); Utils.writeTypedCollection(dest, mRelatedContent); dest.writeInt(mInfoFlags); dest.writeInt(mSignalQuality); dest.writeTypedObject(mMetadata, flags); Utils.writeStringMap(dest, mVendorInfo); } @Override public int describeContents() { return 0; } @Override public String toString() { return "ProgramInfo" + " [selector=" + mSelector + ", logicallyTunedTo=" + Objects.toString(mLogicallyTunedTo) + ", physicallyTunedTo=" + Objects.toString(mPhysicallyTunedTo) + ", relatedContent=" + mRelatedContent.size() + ", infoFlags=" + mInfoFlags + ", mSignalQuality=" + mSignalQuality + ", mMetadata=" + Objects.toString(mMetadata) + "]"; } @Override public int hashCode() { return Objects.hash(mSelector, mLogicallyTunedTo, mPhysicallyTunedTo, mRelatedContent, mInfoFlags, mSignalQuality, mMetadata, mVendorInfo); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof ProgramInfo)) return false; ProgramInfo other = (ProgramInfo) obj; if (!Objects.equals(mSelector, other.mSelector)) return false; if (!Objects.equals(mLogicallyTunedTo, other.mLogicallyTunedTo)) return false; if (!Objects.equals(mPhysicallyTunedTo, other.mPhysicallyTunedTo)) return false; if (!Objects.equals(mRelatedContent, other.mRelatedContent)) return false; if (mInfoFlags != other.mInfoFlags) return false; if (mSignalQuality != other.mSignalQuality) return false; if (!Objects.equals(mMetadata, other.mMetadata)) return false; if (!Objects.equals(mVendorInfo, other.mVendorInfo)) return false; return true; } }
Returns a list of descriptors for all broadcast radio modules present on the device.
Params:
Returns:
/** * Returns a list of descriptors for all broadcast radio modules present on the device. * @param modules An List of {@link ModuleProperties} where the list will be returned. * @return * <ul> * <li>{@link #STATUS_OK} in case of success, </li> * <li>{@link #STATUS_ERROR} in case of unspecified error, </li> * <li>{@link #STATUS_NO_INIT} if the native service cannot be reached, </li> * <li>{@link #STATUS_BAD_VALUE} if modules is null, </li> * <li>{@link #STATUS_DEAD_OBJECT} if the binder transaction to the native service fails, </li> * </ul> */
@RequiresPermission(Manifest.permission.ACCESS_BROADCAST_RADIO) public int listModules(List<ModuleProperties> modules) { if (modules == null) { Log.e(TAG, "the output list must not be empty"); return STATUS_BAD_VALUE; } Log.d(TAG, "Listing available tuners..."); List<ModuleProperties> returnedList; try { returnedList = mService.listModules(); } catch (RemoteException e) { Log.e(TAG, "Failed listing available tuners", e); return STATUS_DEAD_OBJECT; } if (returnedList == null) { Log.e(TAG, "Returned list was a null"); return STATUS_ERROR; } modules.addAll(returnedList); return STATUS_OK; } private native int nativeListModules(List<ModuleProperties> modules);
Open an interface to control a tuner on a given broadcast radio module. Optionally selects and applies the configuration passed as "config" argument.
Params:
  • moduleId – radio module identifier ModuleProperties.getId(). Mandatory.
  • config – desired band and configuration to apply when enabling the hardware module. optional, can be null.
  • withAudio – true to request a tuner with an audio source. This tuner is intended for live listening or recording or a radio program. If false, the tuner can only be used to retrieve program informations.
  • callback – Callback interface. Mandatory.
  • handler – the Handler on which the callbacks will be received. Can be null if default handler is OK.
Returns:a valid RadioTuner interface in case of success or null in case of error.
/** * Open an interface to control a tuner on a given broadcast radio module. * Optionally selects and applies the configuration passed as "config" argument. * @param moduleId radio module identifier {@link ModuleProperties#getId()}. Mandatory. * @param config desired band and configuration to apply when enabling the hardware module. * optional, can be null. * @param withAudio {@code true} to request a tuner with an audio source. * This tuner is intended for live listening or recording or a radio program. * If {@code false}, the tuner can only be used to retrieve program informations. * @param callback {@link RadioTuner.Callback} interface. Mandatory. * @param handler the Handler on which the callbacks will be received. * Can be null if default handler is OK. * @return a valid {@link RadioTuner} interface in case of success or null in case of error. */
@RequiresPermission(Manifest.permission.ACCESS_BROADCAST_RADIO) public RadioTuner openTuner(int moduleId, BandConfig config, boolean withAudio, RadioTuner.Callback callback, Handler handler) { if (callback == null) { throw new IllegalArgumentException("callback must not be empty"); } Log.d(TAG, "Opening tuner " + moduleId + "..."); ITuner tuner; TunerCallbackAdapter halCallback = new TunerCallbackAdapter(callback, handler); try { tuner = mService.openTuner(moduleId, config, withAudio, halCallback); } catch (RemoteException | IllegalArgumentException ex) { Log.e(TAG, "Failed to open tuner", ex); return null; } if (tuner == null) { Log.e(TAG, "Failed to open tuner"); return null; } return new TunerAdapter(tuner, halCallback, config != null ? config.getType() : BAND_INVALID); } private final Map<Announcement.OnListUpdatedListener, ICloseHandle> mAnnouncementListeners = new HashMap<>();
Adds new announcement listener.
Params:
  • enabledAnnouncementTypes – a set of announcement types to listen to
  • listener – announcement listener
/** * Adds new announcement listener. * * @param enabledAnnouncementTypes a set of announcement types to listen to * @param listener announcement listener */
@RequiresPermission(Manifest.permission.ACCESS_BROADCAST_RADIO) public void addAnnouncementListener(@NonNull Set<Integer> enabledAnnouncementTypes, @NonNull Announcement.OnListUpdatedListener listener) { addAnnouncementListener(cmd -> cmd.run(), enabledAnnouncementTypes, listener); }
Adds new announcement listener with executor.
Params:
  • executor – the executor
  • enabledAnnouncementTypes – a set of announcement types to listen to
  • listener – announcement listener
/** * Adds new announcement listener with executor. * * @param executor the executor * @param enabledAnnouncementTypes a set of announcement types to listen to * @param listener announcement listener */
@RequiresPermission(Manifest.permission.ACCESS_BROADCAST_RADIO) public void addAnnouncementListener(@NonNull @CallbackExecutor Executor executor, @NonNull Set<Integer> enabledAnnouncementTypes, @NonNull Announcement.OnListUpdatedListener listener) { Objects.requireNonNull(executor); Objects.requireNonNull(listener); int[] types = enabledAnnouncementTypes.stream().mapToInt(Integer::intValue).toArray(); IAnnouncementListener listenerIface = new IAnnouncementListener.Stub() { public void onListUpdated(List<Announcement> activeAnnouncements) { executor.execute(() -> listener.onListUpdated(activeAnnouncements)); } }; synchronized (mAnnouncementListeners) { ICloseHandle closeHandle = null; try { closeHandle = mService.addAnnouncementListener(types, listenerIface); } catch (RemoteException ex) { ex.rethrowFromSystemServer(); } Objects.requireNonNull(closeHandle); ICloseHandle oldCloseHandle = mAnnouncementListeners.put(listener, closeHandle); if (oldCloseHandle != null) Utils.close(oldCloseHandle); } }
Removes previously registered announcement listener.
Params:
  • listener – announcement listener, previously registered with addAnnouncementListener
/** * Removes previously registered announcement listener. * * @param listener announcement listener, previously registered with * {@link addAnnouncementListener} */
@RequiresPermission(Manifest.permission.ACCESS_BROADCAST_RADIO) public void removeAnnouncementListener(@NonNull Announcement.OnListUpdatedListener listener) { Objects.requireNonNull(listener); synchronized (mAnnouncementListeners) { ICloseHandle closeHandle = mAnnouncementListeners.remove(listener); if (closeHandle != null) Utils.close(closeHandle); } } @NonNull private final Context mContext; @NonNull private final IRadioService mService;
@hide
/** * @hide */
public RadioManager(@NonNull Context context) throws ServiceNotFoundException { mContext = context; mService = IRadioService.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.RADIO_SERVICE)); } }