summaryrefslogtreecommitdiff
path: root/android/hardware/radio
diff options
context:
space:
mode:
authorJustin Klaassen <justinklaassen@google.com>2018-04-03 23:21:57 -0400
committerJustin Klaassen <justinklaassen@google.com>2018-04-03 23:21:57 -0400
commit4d01eeaffaa720e4458a118baa137a11614f00f7 (patch)
tree66751893566986236788e3c796a7cc5e90d05f52 /android/hardware/radio
parenta192cc2a132cb0ee8588e2df755563ec7008c179 (diff)
downloadandroid-28-4d01eeaffaa720e4458a118baa137a11614f00f7.tar.gz
Import Android SDK Platform P [4697573]
/google/data/ro/projects/android/fetch_artifact \ --bid 4697573 \ --target sdk_phone_armv7-win_sdk \ sdk-repo-linux-sources-4697573.zip AndroidVersion.ApiLevel has been modified to appear as 28 Change-Id: If80578c3c657366cc9cf75f8db13d46e2dd4e077
Diffstat (limited to 'android/hardware/radio')
-rw-r--r--android/hardware/radio/ProgramList.java11
-rw-r--r--android/hardware/radio/ProgramSelector.java9
-rw-r--r--android/hardware/radio/RadioManager.java122
-rw-r--r--android/hardware/radio/RadioMetadata.java49
-rw-r--r--android/hardware/radio/RadioTuner.java61
-rw-r--r--android/hardware/radio/TunerAdapter.java36
-rw-r--r--android/hardware/radio/TunerCallbackAdapter.java51
-rw-r--r--android/hardware/radio/Utils.java23
8 files changed, 284 insertions, 78 deletions
diff --git a/android/hardware/radio/ProgramList.java b/android/hardware/radio/ProgramList.java
index b2aa9ba5..e6f523c0 100644
--- a/android/hardware/radio/ProgramList.java
+++ b/android/hardware/radio/ProgramList.java
@@ -263,6 +263,17 @@ public final class ProgramList implements AutoCloseable {
/**
* @hide for framework use only
*/
+ public Filter() {
+ mIdentifierTypes = Collections.emptySet();
+ mIdentifiers = Collections.emptySet();
+ mIncludeCategories = false;
+ mExcludeModifications = false;
+ mVendorFilter = null;
+ }
+
+ /**
+ * @hide for framework use only
+ */
public Filter(@Nullable Map<String, String> vendorFilter) {
mIdentifierTypes = Collections.emptySet();
mIdentifiers = Collections.emptySet();
diff --git a/android/hardware/radio/ProgramSelector.java b/android/hardware/radio/ProgramSelector.java
index 0294a29b..2a878ebb 100644
--- a/android/hardware/radio/ProgramSelector.java
+++ b/android/hardware/radio/ProgramSelector.java
@@ -441,6 +441,15 @@ public final class ProgramSelector implements Parcelable {
*/
public static @NonNull ProgramSelector createAmFmSelector(
@RadioManager.Band int band, int frequencyKhz, int subChannel) {
+ if (band == RadioManager.BAND_INVALID) {
+ // 50MHz is a rough boundary between AM (<30MHz) and FM (>60MHz).
+ if (frequencyKhz < 50000) {
+ band = (subChannel <= 0) ? RadioManager.BAND_AM : RadioManager.BAND_AM_HD;
+ } else {
+ band = (subChannel <= 0) ? RadioManager.BAND_FM : RadioManager.BAND_FM_HD;
+ }
+ }
+
boolean isAm = (band == RadioManager.BAND_AM || band == RadioManager.BAND_AM_HD);
boolean isDigital = (band == RadioManager.BAND_AM_HD || band == RadioManager.BAND_FM_HD);
if (!isAm && !isDigital && band != RadioManager.BAND_FM) {
diff --git a/android/hardware/radio/RadioManager.java b/android/hardware/radio/RadioManager.java
index b00f6033..8263bb8d 100644
--- a/android/hardware/radio/RadioManager.java
+++ b/android/hardware/radio/RadioManager.java
@@ -21,10 +21,12 @@ 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;
@@ -58,6 +60,7 @@ import java.util.stream.Collectors;
*/
@SystemApi
@SystemService(Context.RADIO_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_BROADCAST_RADIO)
public class RadioManager {
private static final String TAG = "BroadcastRadio.manager";
@@ -208,19 +211,23 @@ public class RadioManager {
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 */
public ModuleProperties(int id, String serviceName, int classId, String implementor,
String product, String version, String serial, int numTuners, int numAudioSources,
- boolean isCaptureSupported, BandDescriptor[] bands, boolean isBgScanSupported,
+ 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;
@@ -231,11 +238,19 @@ public class RadioManager {
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;
}
@@ -317,6 +332,18 @@ public class RadioManager {
return mNumAudioSources;
}
+ /**
+ * 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;
+ }
+
/** {@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.
@@ -363,6 +390,19 @@ public class RadioManager {
}
/**
+ * 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.
*
@@ -394,6 +434,7 @@ public class RadioManager {
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];
@@ -403,6 +444,7 @@ public class RadioManager {
mIsBgScanSupported = in.readInt() == 1;
mSupportedProgramTypes = arrayToSet(in.createIntArray());
mSupportedIdentifierTypes = arrayToSet(in.createIntArray());
+ mDabFrequencyTable = Utils.readStringIntMap(in);
mVendorInfo = Utils.readStringMap(in);
}
@@ -428,11 +470,13 @@ public class RadioManager {
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);
}
@@ -449,6 +493,7 @@ public class RadioManager {
+ ", mVersion=" + mVersion + ", mSerial=" + mSerial
+ ", mNumTuners=" + mNumTuners
+ ", mNumAudioSources=" + mNumAudioSources
+ + ", mIsInitializationRequired=" + mIsInitializationRequired
+ ", mIsCaptureSupported=" + mIsCaptureSupported
+ ", mIsBgScanSupported=" + mIsBgScanSupported
+ ", mBands=" + Arrays.toString(mBands) + "]";
@@ -456,67 +501,32 @@ public class RadioManager {
@Override
public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + mId;
- result = prime * result + mServiceName.hashCode();
- result = prime * result + mClassId;
- result = prime * result + ((mImplementor == null) ? 0 : mImplementor.hashCode());
- result = prime * result + ((mProduct == null) ? 0 : mProduct.hashCode());
- result = prime * result + ((mVersion == null) ? 0 : mVersion.hashCode());
- result = prime * result + ((mSerial == null) ? 0 : mSerial.hashCode());
- result = prime * result + mNumTuners;
- result = prime * result + mNumAudioSources;
- result = prime * result + (mIsCaptureSupported ? 1 : 0);
- result = prime * result + Arrays.hashCode(mBands);
- result = prime * result + (mIsBgScanSupported ? 1 : 0);
- result = prime * result + mVendorInfo.hashCode();
- return result;
+ 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;
+ if (this == obj) return true;
+ if (!(obj instanceof ModuleProperties)) return false;
ModuleProperties other = (ModuleProperties) obj;
- if (mId != other.getId())
- return false;
+
+ if (mId != other.getId()) return false;
if (!TextUtils.equals(mServiceName, other.mServiceName)) return false;
- if (mClassId != other.getClassId())
- return false;
- if (mImplementor == null) {
- if (other.getImplementor() != null)
- return false;
- } else if (!mImplementor.equals(other.getImplementor()))
- return false;
- if (mProduct == null) {
- if (other.getProduct() != null)
- return false;
- } else if (!mProduct.equals(other.getProduct()))
- return false;
- if (mVersion == null) {
- if (other.getVersion() != null)
- return false;
- } else if (!mVersion.equals(other.getVersion()))
- return false;
- if (mSerial == null) {
- if (other.getSerial() != null)
- return false;
- } else if (!mSerial.equals(other.getSerial()))
- return false;
- if (mNumTuners != other.getNumTuners())
- return false;
- if (mNumAudioSources != other.getNumAudioSources())
- return false;
- if (mIsCaptureSupported != other.isCaptureSupported())
- return false;
- if (!Arrays.equals(mBands, other.getBands()))
- return false;
- if (mIsBgScanSupported != other.isBackgroundScanningSupported())
- return false;
- if (!mVendorInfo.equals(other.mVendorInfo)) 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;
}
}
diff --git a/android/hardware/radio/RadioMetadata.java b/android/hardware/radio/RadioMetadata.java
index 3cc4b566..6e510607 100644
--- a/android/hardware/radio/RadioMetadata.java
+++ b/android/hardware/radio/RadioMetadata.java
@@ -96,6 +96,48 @@ public final class RadioMetadata implements Parcelable {
*/
public static final String METADATA_KEY_CLOCK = "android.hardware.radio.metadata.CLOCK";
+ /**
+ * Technology-independent program name (station name).
+ */
+ public static final String METADATA_KEY_PROGRAM_NAME =
+ "android.hardware.radio.metadata.PROGRAM_NAME";
+
+ /**
+ * DAB ensemble name.
+ */
+ public static final String METADATA_KEY_DAB_ENSEMBLE_NAME =
+ "android.hardware.radio.metadata.DAB_ENSEMBLE_NAME";
+
+ /**
+ * DAB ensemble name - short version (up to 8 characters).
+ */
+ public static final String METADATA_KEY_DAB_ENSEMBLE_NAME_SHORT =
+ "android.hardware.radio.metadata.DAB_ENSEMBLE_NAME_SHORT";
+
+ /**
+ * DAB service name.
+ */
+ public static final String METADATA_KEY_DAB_SERVICE_NAME =
+ "android.hardware.radio.metadata.DAB_SERVICE_NAME";
+
+ /**
+ * DAB service name - short version (up to 8 characters).
+ */
+ public static final String METADATA_KEY_DAB_SERVICE_NAME_SHORT =
+ "android.hardware.radio.metadata.DAB_SERVICE_NAME_SHORT";
+
+ /**
+ * DAB component name.
+ */
+ public static final String METADATA_KEY_DAB_COMPONENT_NAME =
+ "android.hardware.radio.metadata.DAB_COMPONENT_NAME";
+
+ /**
+ * DAB component name.
+ */
+ public static final String METADATA_KEY_DAB_COMPONENT_NAME_SHORT =
+ "android.hardware.radio.metadata.DAB_COMPONENT_NAME_SHORT";
+
private static final int METADATA_TYPE_INVALID = -1;
private static final int METADATA_TYPE_INT = 0;
@@ -119,6 +161,13 @@ public final class RadioMetadata implements Parcelable {
METADATA_KEYS_TYPE.put(METADATA_KEY_ICON, METADATA_TYPE_BITMAP);
METADATA_KEYS_TYPE.put(METADATA_KEY_ART, METADATA_TYPE_BITMAP);
METADATA_KEYS_TYPE.put(METADATA_KEY_CLOCK, METADATA_TYPE_CLOCK);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_PROGRAM_NAME, METADATA_TYPE_TEXT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_ENSEMBLE_NAME, METADATA_TYPE_TEXT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_ENSEMBLE_NAME_SHORT, METADATA_TYPE_TEXT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_SERVICE_NAME, METADATA_TYPE_TEXT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_SERVICE_NAME_SHORT, METADATA_TYPE_TEXT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_COMPONENT_NAME, METADATA_TYPE_TEXT);
+ METADATA_KEYS_TYPE.put(METADATA_KEY_DAB_COMPONENT_NAME_SHORT, METADATA_TYPE_TEXT);
}
// keep in sync with: system/media/radio/include/system/radio_metadata.h
diff --git a/android/hardware/radio/RadioTuner.java b/android/hardware/radio/RadioTuner.java
index ed20c4aa..0edd0553 100644
--- a/android/hardware/radio/RadioTuner.java
+++ b/android/hardware/radio/RadioTuner.java
@@ -64,7 +64,9 @@ public abstract class RadioTuner {
* <li>{@link RadioManager#STATUS_DEAD_OBJECT} if the binder transaction to the native
* service fails, </li>
* </ul>
+ * @deprecated Only applicable for HAL 1.x.
*/
+ @Deprecated
public abstract int setConfiguration(RadioManager.BandConfig config);
/**
@@ -80,7 +82,10 @@ public abstract class RadioTuner {
* <li>{@link RadioManager#STATUS_DEAD_OBJECT} if the binder transaction to the native
* service fails, </li>
* </ul>
+ *
+ * @deprecated Only applicable for HAL 1.x.
*/
+ @Deprecated
public abstract int getConfiguration(RadioManager.BandConfig[] config);
@@ -228,7 +233,9 @@ public abstract class RadioTuner {
* <li>{@link RadioManager#STATUS_DEAD_OBJECT} if the binder transaction to the native
* service fails, </li>
* </ul>
+ * @deprecated Use {@link onProgramInfoChanged} callback instead.
*/
+ @Deprecated
public abstract int getProgramInformation(RadioManager.ProgramInfo[] info);
/**
@@ -427,7 +434,10 @@ public abstract class RadioTuner {
* Get current antenna connection state for current configuration.
* Only valid if a configuration has been applied.
* @return {@code true} if the antenna is connected, {@code false} otherwise.
+ *
+ * @deprecated Use {@link onAntennaState} callback instead
*/
+ @Deprecated
public abstract boolean isAntennaConnected();
/**
@@ -446,20 +456,41 @@ public abstract class RadioTuner {
public abstract boolean hasControl();
/** Indicates a failure of radio IC or driver.
- * The application must close and re open the tuner */
+ * The application must close and re open the tuner
+ * @deprecated See {@link onError} callback.
+ */
+ @Deprecated
public static final int ERROR_HARDWARE_FAILURE = 0;
/** Indicates a failure of the radio service.
- * The application must close and re open the tuner */
+ * The application must close and re open the tuner
+ * @deprecated See {@link onError} callback.
+ */
+ @Deprecated
public static final int ERROR_SERVER_DIED = 1;
- /** A pending seek or tune operation was cancelled */
+ /** A pending seek or tune operation was cancelled
+ * @deprecated See {@link onError} callback.
+ */
+ @Deprecated
public static final int ERROR_CANCELLED = 2;
- /** A pending seek or tune operation timed out */
+ /** A pending seek or tune operation timed out
+ * @deprecated See {@link onError} callback.
+ */
+ @Deprecated
public static final int ERROR_SCAN_TIMEOUT = 3;
- /** The requested configuration could not be applied */
+ /** The requested configuration could not be applied
+ * @deprecated See {@link onError} callback.
+ */
+ @Deprecated
public static final int ERROR_CONFIG = 4;
- /** Background scan was interrupted due to hardware becoming temporarily unavailable. */
+ /** Background scan was interrupted due to hardware becoming temporarily unavailable.
+ * @deprecated See {@link onError} callback.
+ */
+ @Deprecated
public static final int ERROR_BACKGROUND_SCAN_UNAVAILABLE = 5;
- /** Background scan failed due to other error, ie. HW failure. */
+ /** Background scan failed due to other error, ie. HW failure.
+ * @deprecated See {@link onError} callback.
+ */
+ @Deprecated
public static final int ERROR_BACKGROUND_SCAN_FAILED = 6;
/**
@@ -473,13 +504,29 @@ public abstract class RadioTuner {
* status is one of {@link #ERROR_HARDWARE_FAILURE}, {@link #ERROR_SERVER_DIED},
* {@link #ERROR_CANCELLED}, {@link #ERROR_SCAN_TIMEOUT},
* {@link #ERROR_CONFIG}
+ *
+ * @deprecated Use {@link onTuneFailed} for tune, scan and step;
+ * other use cases (configuration, background scan) are already deprecated.
*/
public void onError(int status) {}
+
+ /**
+ * Called when tune, scan or step operation fails.
+ *
+ * @param result cause of the failure
+ * @param selector ProgramSelector argument of tune that failed;
+ * null for scan and step.
+ */
+ public void onTuneFailed(int result, @Nullable ProgramSelector selector) {}
+
/**
* onConfigurationChanged() is called upon successful completion of
* {@link RadioManager#openTuner(int, RadioManager.BandConfig, boolean, Callback, Handler)}
* or {@link RadioTuner#setConfiguration(RadioManager.BandConfig)}
+ *
+ * @deprecated Only applicable for HAL 1.x.
*/
+ @Deprecated
public void onConfigurationChanged(RadioManager.BandConfig config) {}
/**
diff --git a/android/hardware/radio/TunerAdapter.java b/android/hardware/radio/TunerAdapter.java
index 91944bfd..be2846f8 100644
--- a/android/hardware/radio/TunerAdapter.java
+++ b/android/hardware/radio/TunerAdapter.java
@@ -60,6 +60,7 @@ class TunerAdapter extends RadioTuner {
mLegacyListProxy.close();
mLegacyListProxy = null;
}
+ mCallback.close();
}
try {
mTuner.close();
@@ -202,15 +203,17 @@ class TunerAdapter extends RadioTuner {
@Override
public int getProgramInformation(RadioManager.ProgramInfo[] info) {
if (info == null || info.length != 1) {
- throw new IllegalArgumentException("The argument must be an array of length 1");
+ Log.e(TAG, "The argument must be an array of length 1");
+ return RadioManager.STATUS_BAD_VALUE;
}
- try {
- info[0] = mTuner.getProgramInformation();
- return RadioManager.STATUS_OK;
- } catch (RemoteException e) {
- Log.e(TAG, "service died", e);
- return RadioManager.STATUS_DEAD_OBJECT;
+
+ RadioManager.ProgramInfo current = mCallback.getCurrentProgramInformation();
+ if (current == null) {
+ Log.w(TAG, "Didn't get program info yet");
+ return RadioManager.STATUS_INVALID_OPERATION;
}
+ info[0] = current;
+ return RadioManager.STATUS_OK;
}
@Override
@@ -276,6 +279,7 @@ class TunerAdapter extends RadioTuner {
try {
mTuner.startProgramListUpdates(filter);
} catch (UnsupportedOperationException ex) {
+ Log.i(TAG, "Program list is not supported with this hardware");
return null;
} catch (RemoteException ex) {
mCallback.setProgramListObserver(null, () -> { });
@@ -288,12 +292,20 @@ class TunerAdapter extends RadioTuner {
@Override
public boolean isAnalogForced() {
- return isConfigFlagSet(RadioManager.CONFIG_FORCE_ANALOG);
+ try {
+ return isConfigFlagSet(RadioManager.CONFIG_FORCE_ANALOG);
+ } catch (UnsupportedOperationException ex) {
+ throw new IllegalStateException(ex);
+ }
}
@Override
public void setAnalogForced(boolean isForced) {
- setConfigFlag(RadioManager.CONFIG_FORCE_ANALOG, isForced);
+ try {
+ setConfigFlag(RadioManager.CONFIG_FORCE_ANALOG, isForced);
+ } catch (UnsupportedOperationException ex) {
+ throw new IllegalStateException(ex);
+ }
}
@Override
@@ -343,11 +355,7 @@ class TunerAdapter extends RadioTuner {
@Override
public boolean isAntennaConnected() {
- try {
- return mTuner.isAntennaConnected();
- } catch (RemoteException e) {
- throw new RuntimeException("service died", e);
- }
+ return mCallback.isAntennaConnected();
}
@Override
diff --git a/android/hardware/radio/TunerCallbackAdapter.java b/android/hardware/radio/TunerCallbackAdapter.java
index b299ffe0..0fb93e53 100644
--- a/android/hardware/radio/TunerCallbackAdapter.java
+++ b/android/hardware/radio/TunerCallbackAdapter.java
@@ -37,8 +37,12 @@ class TunerCallbackAdapter extends ITunerCallback.Stub {
@NonNull private final Handler mHandler;
@Nullable ProgramList mProgramList;
- @Nullable List<RadioManager.ProgramInfo> mLastCompleteList; // for legacy getProgramList call
+
+ // cache for deprecated methods
+ boolean mIsAntennaConnected = true;
+ @Nullable List<RadioManager.ProgramInfo> mLastCompleteList;
private boolean mDelayedCompleteCallback = false;
+ @Nullable RadioManager.ProgramInfo mCurrentProgramInfo;
TunerCallbackAdapter(@NonNull RadioTuner.Callback callback, @Nullable Handler handler) {
mCallback = callback;
@@ -49,6 +53,12 @@ class TunerCallbackAdapter extends ITunerCallback.Stub {
}
}
+ void close() {
+ synchronized (mLock) {
+ if (mProgramList != null) mProgramList.close();
+ }
+ }
+
void setProgramListObserver(@Nullable ProgramList programList,
@NonNull ProgramList.OnCloseListener closeListener) {
Objects.requireNonNull(closeListener);
@@ -92,12 +102,46 @@ class TunerCallbackAdapter extends ITunerCallback.Stub {
}
}
+ @Nullable RadioManager.ProgramInfo getCurrentProgramInformation() {
+ synchronized (mLock) {
+ return mCurrentProgramInfo;
+ }
+ }
+
+ boolean isAntennaConnected() {
+ return mIsAntennaConnected;
+ }
+
@Override
public void onError(int status) {
mHandler.post(() -> mCallback.onError(status));
}
@Override
+ public void onTuneFailed(int status, @Nullable ProgramSelector selector) {
+ mHandler.post(() -> mCallback.onTuneFailed(status, selector));
+
+ int errorCode;
+ switch (status) {
+ case RadioManager.STATUS_PERMISSION_DENIED:
+ case RadioManager.STATUS_DEAD_OBJECT:
+ errorCode = RadioTuner.ERROR_SERVER_DIED;
+ break;
+ case RadioManager.STATUS_ERROR:
+ case RadioManager.STATUS_NO_INIT:
+ case RadioManager.STATUS_BAD_VALUE:
+ case RadioManager.STATUS_INVALID_OPERATION:
+ Log.i(TAG, "Got an error with no mapping to the legacy API (" + status
+ + "), doing a best-effort conversion to ERROR_SCAN_TIMEOUT");
+ // fall through
+ case RadioManager.STATUS_TIMED_OUT:
+ default:
+ errorCode = RadioTuner.ERROR_SCAN_TIMEOUT;
+ }
+ mHandler.post(() -> mCallback.onError(errorCode));
+ }
+
+ @Override
public void onConfigurationChanged(RadioManager.BandConfig config) {
mHandler.post(() -> mCallback.onConfigurationChanged(config));
}
@@ -109,6 +153,10 @@ class TunerCallbackAdapter extends ITunerCallback.Stub {
return;
}
+ synchronized (mLock) {
+ mCurrentProgramInfo = info;
+ }
+
mHandler.post(() -> {
mCallback.onProgramInfoChanged(info);
@@ -129,6 +177,7 @@ class TunerCallbackAdapter extends ITunerCallback.Stub {
@Override
public void onAntennaState(boolean connected) {
+ mIsAntennaConnected = connected;
mHandler.post(() -> mCallback.onAntennaState(connected));
}
diff --git a/android/hardware/radio/Utils.java b/android/hardware/radio/Utils.java
index f1b58974..9887f782 100644
--- a/android/hardware/radio/Utils.java
+++ b/android/hardware/radio/Utils.java
@@ -56,6 +56,29 @@ final class Utils {
return map;
}
+ static void writeStringIntMap(@NonNull Parcel dest, @Nullable Map<String, Integer> map) {
+ if (map == null) {
+ dest.writeInt(0);
+ return;
+ }
+ dest.writeInt(map.size());
+ for (Map.Entry<String, Integer> entry : map.entrySet()) {
+ dest.writeString(entry.getKey());
+ dest.writeInt(entry.getValue());
+ }
+ }
+
+ static @NonNull Map<String, Integer> readStringIntMap(@NonNull Parcel in) {
+ int size = in.readInt();
+ Map<String, Integer> map = new HashMap<>();
+ while (size-- > 0) {
+ String key = in.readString();
+ int value = in.readInt();
+ map.put(key, value);
+ }
+ return map;
+ }
+
static <T extends Parcelable> void writeSet(@NonNull Parcel dest, @Nullable Set<T> set) {
if (set == null) {
dest.writeInt(0);