summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/system-current.txt27
-rw-r--r--core/java/android/hardware/radio/ITuner.aidl4
-rw-r--r--core/java/android/hardware/radio/ITunerCallback.aidl2
-rw-r--r--core/java/android/hardware/radio/RadioTuner.java61
-rw-r--r--core/java/android/hardware/radio/TunerAdapter.java34
-rw-r--r--core/java/android/hardware/radio/TunerCallbackAdapter.java45
-rw-r--r--core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java1
-rw-r--r--services/core/java/com/android/server/broadcastradio/hal1/Tuner.java21
-rw-r--r--services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java6
-rw-r--r--services/core/java/com/android/server/broadcastradio/hal2/Convert.java52
-rw-r--r--services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java42
-rw-r--r--services/core/java/com/android/server/broadcastradio/hal2/TunerCallback.java16
-rw-r--r--services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java53
-rw-r--r--services/core/java/com/android/server/broadcastradio/hal2/Utils.java28
-rw-r--r--services/core/jni/BroadcastRadio/BroadcastRadioService.cpp9
-rw-r--r--services/core/jni/BroadcastRadio/Tuner.cpp51
16 files changed, 293 insertions, 159 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index a54a06f3d4c4..494b9b2c9f74 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2057,21 +2057,21 @@ package android.hardware.radio {
method public abstract int cancel();
method public abstract void cancelAnnouncement();
method public abstract void close();
- method public abstract int getConfiguration(android.hardware.radio.RadioManager.BandConfig[]);
+ method public abstract deprecated int getConfiguration(android.hardware.radio.RadioManager.BandConfig[]);
method public android.hardware.radio.ProgramList getDynamicProgramList(android.hardware.radio.ProgramList.Filter);
method public abstract boolean getMute();
method public java.util.Map<java.lang.String, java.lang.String> getParameters(java.util.List<java.lang.String>);
- method public abstract int getProgramInformation(android.hardware.radio.RadioManager.ProgramInfo[]);
+ method public abstract deprecated int getProgramInformation(android.hardware.radio.RadioManager.ProgramInfo[]);
method public abstract deprecated java.util.List<android.hardware.radio.RadioManager.ProgramInfo> getProgramList(java.util.Map<java.lang.String, java.lang.String>);
method public abstract boolean hasControl();
method public abstract deprecated boolean isAnalogForced();
- method public abstract boolean isAntennaConnected();
+ method public abstract deprecated boolean isAntennaConnected();
method public boolean isConfigFlagSet(int);
method public boolean isConfigFlagSupported(int);
method public abstract int scan(int, boolean);
method public abstract deprecated void setAnalogForced(boolean);
method public void setConfigFlag(int, boolean);
- method public abstract int setConfiguration(android.hardware.radio.RadioManager.BandConfig);
+ method public abstract deprecated int setConfiguration(android.hardware.radio.RadioManager.BandConfig);
method public abstract int setMute(boolean);
method public java.util.Map<java.lang.String, java.lang.String> setParameters(java.util.Map<java.lang.String, java.lang.String>);
method public abstract boolean startBackgroundScan();
@@ -2080,13 +2080,13 @@ package android.hardware.radio {
method public abstract void tune(android.hardware.radio.ProgramSelector);
field public static final int DIRECTION_DOWN = 1; // 0x1
field public static final int DIRECTION_UP = 0; // 0x0
- field public static final int ERROR_BACKGROUND_SCAN_FAILED = 6; // 0x6
- field public static final int ERROR_BACKGROUND_SCAN_UNAVAILABLE = 5; // 0x5
- field public static final int ERROR_CANCELLED = 2; // 0x2
- field public static final int ERROR_CONFIG = 4; // 0x4
- field public static final int ERROR_HARDWARE_FAILURE = 0; // 0x0
- field public static final int ERROR_SCAN_TIMEOUT = 3; // 0x3
- field public static final int ERROR_SERVER_DIED = 1; // 0x1
+ field public static final deprecated int ERROR_BACKGROUND_SCAN_FAILED = 6; // 0x6
+ field public static final deprecated int ERROR_BACKGROUND_SCAN_UNAVAILABLE = 5; // 0x5
+ field public static final deprecated int ERROR_CANCELLED = 2; // 0x2
+ field public static final deprecated int ERROR_CONFIG = 4; // 0x4
+ field public static final deprecated int ERROR_HARDWARE_FAILURE = 0; // 0x0
+ field public static final deprecated int ERROR_SCAN_TIMEOUT = 3; // 0x3
+ field public static final deprecated int ERROR_SERVER_DIED = 1; // 0x1
}
public static abstract class RadioTuner.Callback {
@@ -2094,15 +2094,16 @@ package android.hardware.radio {
method public void onAntennaState(boolean);
method public void onBackgroundScanAvailabilityChange(boolean);
method public void onBackgroundScanComplete();
- method public void onConfigurationChanged(android.hardware.radio.RadioManager.BandConfig);
+ method public deprecated void onConfigurationChanged(android.hardware.radio.RadioManager.BandConfig);
method public void onControlChanged(boolean);
method public void onEmergencyAnnouncement(boolean);
- method public void onError(int);
+ method public deprecated void onError(int);
method public deprecated void onMetadataChanged(android.hardware.radio.RadioMetadata);
method public void onParametersUpdated(java.util.Map<java.lang.String, java.lang.String>);
method public void onProgramInfoChanged(android.hardware.radio.RadioManager.ProgramInfo);
method public void onProgramListChanged();
method public void onTrafficAnnouncement(boolean);
+ method public void onTuneFailed(int, android.hardware.radio.ProgramSelector);
}
}
diff --git a/core/java/android/hardware/radio/ITuner.aidl b/core/java/android/hardware/radio/ITuner.aidl
index bf5e391794f5..429f1f351a93 100644
--- a/core/java/android/hardware/radio/ITuner.aidl
+++ b/core/java/android/hardware/radio/ITuner.aidl
@@ -64,8 +64,6 @@ interface ITuner {
void cancelAnnouncement();
- RadioManager.ProgramInfo getProgramInformation();
-
Bitmap getImage(int id);
/**
@@ -92,6 +90,4 @@ interface ITuner {
* @return Vendor-specific key-value pairs, must be Map<String, String>
*/
Map getParameters(in List<String> keys);
-
- boolean isAntennaConnected();
}
diff --git a/core/java/android/hardware/radio/ITunerCallback.aidl b/core/java/android/hardware/radio/ITunerCallback.aidl
index 54af30fcc35e..b32daa5a7609 100644
--- a/core/java/android/hardware/radio/ITunerCallback.aidl
+++ b/core/java/android/hardware/radio/ITunerCallback.aidl
@@ -17,12 +17,14 @@
package android.hardware.radio;
import android.hardware.radio.ProgramList;
+import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
import android.hardware.radio.RadioMetadata;
/** {@hide} */
oneway interface ITunerCallback {
void onError(int status);
+ void onTuneFailed(int result, in ProgramSelector selector);
void onConfigurationChanged(in RadioManager.BandConfig config);
void onCurrentProgramInfoChanged(in RadioManager.ProgramInfo info);
void onTrafficAnnouncement(boolean active);
diff --git a/core/java/android/hardware/radio/RadioTuner.java b/core/java/android/hardware/radio/RadioTuner.java
index ed20c4aad761..0edd05533dd3 100644
--- a/core/java/android/hardware/radio/RadioTuner.java
+++ b/core/java/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/core/java/android/hardware/radio/TunerAdapter.java b/core/java/android/hardware/radio/TunerAdapter.java
index 91944bfd04f0..85f3115689cd 100644
--- a/core/java/android/hardware/radio/TunerAdapter.java
+++ b/core/java/android/hardware/radio/TunerAdapter.java
@@ -202,15 +202,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
@@ -288,12 +290,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 +353,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/core/java/android/hardware/radio/TunerCallbackAdapter.java b/core/java/android/hardware/radio/TunerCallbackAdapter.java
index b299ffe042b2..7437c40351db 100644
--- a/core/java/android/hardware/radio/TunerCallbackAdapter.java
+++ b/core/java/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;
@@ -92,12 +96,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 +147,10 @@ class TunerCallbackAdapter extends ITunerCallback.Stub {
return;
}
+ synchronized (mLock) {
+ mCurrentProgramInfo = info;
+ }
+
mHandler.post(() -> {
mCallback.onProgramInfoChanged(info);
@@ -129,6 +171,7 @@ class TunerCallbackAdapter extends ITunerCallback.Stub {
@Override
public void onAntennaState(boolean connected) {
+ mIsAntennaConnected = connected;
mHandler.post(() -> mCallback.onAntennaState(connected));
}
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
index 896fd15d90cd..370659eb99d9 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
@@ -122,6 +122,7 @@ public class RadioTunerTest {
private void resetCallback() {
verify(mCallback, atLeast(0)).onMetadataChanged(any());
+ verify(mCallback, atLeast(0)).onProgramInfoChanged(any());
verifyNoMoreInteractions(mCallback);
Mockito.reset(mCallback);
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
index f9b35f53d4d5..e77cb7a7ad94 100644
--- a/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
+++ b/services/core/java/com/android/server/broadcastradio/hal1/Tuner.java
@@ -48,7 +48,7 @@ class Tuner extends ITuner.Stub {
private boolean mIsClosed = false;
private boolean mIsMuted = false;
- private int mRegion; // TODO(b/62710330): find better solution to handle regions
+ private int mRegion;
private final boolean mWithAudio;
Tuner(@NonNull ITunerCallback clientCallback, int halRev,
@@ -89,7 +89,6 @@ class Tuner extends ITuner.Stub {
private native void nativeCancelAnnouncement(long nativeContext);
- private native RadioManager.ProgramInfo nativeGetProgramInformation(long nativeContext);
private native boolean nativeStartBackgroundScan(long nativeContext);
private native List<RadioManager.ProgramInfo> nativeGetProgramList(long nativeContext,
Map<String, String> vendorFilter);
@@ -103,8 +102,6 @@ class Tuner extends ITuner.Stub {
Map<String, String> parameters);
private native Map<String, String> nativeGetParameters(long nativeContext, List<String> keys);
- private native boolean nativeIsAntennaConnected(long nativeContext);
-
@Override
public void close() {
synchronized (mLock) {
@@ -218,14 +215,6 @@ class Tuner extends ITuner.Stub {
}
@Override
- public RadioManager.ProgramInfo getProgramInformation() {
- synchronized (mLock) {
- checkNotClosedLocked();
- return nativeGetProgramInformation(mNativeContext);
- }
- }
-
- @Override
public Bitmap getImage(int id) {
if (id == 0) {
throw new IllegalArgumentException("Image ID is missing");
@@ -324,12 +313,4 @@ class Tuner extends ITuner.Stub {
if (results == null) return Collections.emptyMap();
return results;
}
-
- @Override
- public boolean isAntennaConnected() {
- synchronized (mLock) {
- checkNotClosedLocked();
- return nativeIsAntennaConnected(mNativeContext);
- }
- }
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java b/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
index 18f56ed58475..04c0e5788e7b 100644
--- a/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
+++ b/services/core/java/com/android/server/broadcastradio/hal1/TunerCallback.java
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.hardware.radio.ITuner;
import android.hardware.radio.ITunerCallback;
import android.hardware.radio.ProgramList;
+import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
import android.hardware.radio.RadioMetadata;
import android.hardware.radio.RadioTuner;
@@ -100,6 +101,11 @@ class TunerCallback implements ITunerCallback {
}
@Override
+ public void onTuneFailed(int result, ProgramSelector selector) {
+ Slog.e(TAG, "Not applicable for HAL 1.x");
+ }
+
+ @Override
public void onConfigurationChanged(RadioManager.BandConfig config) {
dispatch(() -> mClientCallback.onConfigurationChanged(config));
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/Convert.java b/services/core/java/com/android/server/broadcastradio/hal2/Convert.java
index 7a95971ca517..3bb3d1fdd032 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/Convert.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/Convert.java
@@ -73,7 +73,26 @@ class Convert {
}
}
- private static @NonNull Map<String, String>
+ static @NonNull ArrayList<VendorKeyValue>
+ vendorInfoToHal(@Nullable Map<String, String> info) {
+ if (info == null) return new ArrayList<>();
+
+ ArrayList<VendorKeyValue> list = new ArrayList<>();
+ for (Map.Entry<String, String> entry : info.entrySet()) {
+ VendorKeyValue elem = new VendorKeyValue();
+ elem.key = entry.getKey();
+ elem.value = entry.getValue();
+ if (elem.key == null || elem.value == null) {
+ Slog.w(TAG, "VendorKeyValue contains null pointers");
+ continue;
+ }
+ list.add(elem);
+ }
+
+ return list;
+ }
+
+ static @NonNull Map<String, String>
vendorInfoFromHal(@Nullable List<VendorKeyValue> info) {
if (info == null) return Collections.emptyMap();
@@ -206,18 +225,23 @@ class Convert {
false, // isCaptureSupported
amfmConfigToBands(amfmConfig),
- false, // isBgScanSupported is deprecated
+ true, // isBgScanSupported is deprecated
supportedProgramTypes,
supportedIdentifierTypes,
vendorInfoFromHal(prop.vendorInfo)
);
}
- static @NonNull ProgramIdentifier programIdentifierToHal(
+ static void programIdentifierToHal(@NonNull ProgramIdentifier hwId,
@NonNull ProgramSelector.Identifier id) {
- ProgramIdentifier hwId = new ProgramIdentifier();
hwId.type = id.getType();
hwId.value = id.getValue();
+ }
+
+ static @NonNull ProgramIdentifier programIdentifierToHal(
+ @NonNull ProgramSelector.Identifier id) {
+ ProgramIdentifier hwId = new ProgramIdentifier();
+ programIdentifierToHal(hwId, id);
return hwId;
}
@@ -227,10 +251,22 @@ class Convert {
return new ProgramSelector.Identifier(id.type, id.value);
}
+ static @NonNull android.hardware.broadcastradio.V2_0.ProgramSelector programSelectorToHal(
+ @NonNull ProgramSelector sel) {
+ android.hardware.broadcastradio.V2_0.ProgramSelector hwSel =
+ new android.hardware.broadcastradio.V2_0.ProgramSelector();
+
+ programIdentifierToHal(hwSel.primaryId, sel.getPrimaryId());
+ Arrays.stream(sel.getSecondaryIds()).map(Convert::programIdentifierToHal).
+ forEachOrdered(hwSel.secondaryIds::add);
+
+ return hwSel;
+ }
+
static @NonNull ProgramSelector programSelectorFromHal(
@NonNull android.hardware.broadcastradio.V2_0.ProgramSelector sel) {
ProgramSelector.Identifier[] secondaryIds = sel.secondaryIds.stream().
- map(id -> Objects.requireNonNull(programIdentifierFromHal(id))).
+ map(Convert::programIdentifierFromHal).map(Objects::requireNonNull).
toArray(ProgramSelector.Identifier[]::new);
return new ProgramSelector(
@@ -286,4 +322,10 @@ class Convert {
vendorInfoFromHal(hwAnnouncement.vendorInfo)
);
}
+
+ static <T> @Nullable ArrayList<T> listToArrayList(@Nullable List<T> list) {
+ if (list == null) return null;
+ if (list instanceof ArrayList) return (ArrayList) list;
+ return new ArrayList<>(list);
+ }
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
index 4dff9e06000a..50f032d659b7 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
@@ -18,6 +18,8 @@ package com.android.server.broadcastradio.hal2;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.hardware.radio.ITuner;
import android.hardware.radio.RadioManager;
import android.hardware.broadcastradio.V2_0.AmFmRegionConfig;
@@ -76,15 +78,17 @@ class RadioModule {
Mutable<ITunerSession> hwSession = new Mutable<>();
MutableInt halResult = new MutableInt(Result.UNKNOWN_ERROR);
- mService.openSession(cb, (int result, ITunerSession session) -> {
- hwSession.value = session;
- halResult.value = result;
- });
+ synchronized (mService) {
+ mService.openSession(cb, (result, session) -> {
+ hwSession.value = session;
+ halResult.value = result;
+ });
+ }
Convert.throwOnError("openSession", halResult.value);
Objects.requireNonNull(hwSession.value);
- return new TunerSession(hwSession.value, cb);
+ return new TunerSession(this, hwSession.value, cb);
}
public android.hardware.radio.ICloseHandle addAnnouncementListener(@NonNull int[] enabledTypes,
@@ -103,10 +107,13 @@ class RadioModule {
map(a -> Convert.announcementFromHal(a)).collect(Collectors.toList()));
}
};
- mService.registerAnnouncementListener(enabledList, hwListener, (result, closeHandle) -> {
- halResult.value = result;
- hwCloseHandle.value = closeHandle;
- });
+
+ synchronized (mService) {
+ mService.registerAnnouncementListener(enabledList, hwListener, (result, closeHnd) -> {
+ halResult.value = result;
+ hwCloseHandle.value = closeHnd;
+ });
+ }
Convert.throwOnError("addAnnouncementListener", halResult.value);
return new android.hardware.radio.ICloseHandle.Stub() {
@@ -119,4 +126,21 @@ class RadioModule {
}
};
}
+
+ Bitmap getImage(int id) {
+ if (id == 0) throw new IllegalArgumentException("Image ID is missing");
+
+ byte[] rawImage;
+ synchronized (mService) {
+ List<Byte> rawList = Utils.maybeRethrow(() -> mService.getImage(id));
+ rawImage = new byte[rawList.size()];
+ for (int i = 0; i < rawList.size(); i++) {
+ rawImage[i] = rawList.get(i);
+ }
+ }
+
+ if (rawImage == null || rawImage.length == 0) return null;
+
+ return BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
+ }
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerCallback.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerCallback.java
index ed2a1b3ce851..3c4b49c91cf2 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerCallback.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerCallback.java
@@ -50,10 +50,14 @@ class TunerCallback extends ITunerCallback.Stub {
}
@Override
- public void onTuneFailed(int result, ProgramSelector selector) {}
+ public void onTuneFailed(int result, ProgramSelector selector) {
+ dispatch(() -> mClientCb.onTuneFailed(result, Convert.programSelectorFromHal(selector)));
+ }
@Override
- public void onCurrentProgramInfoChanged(ProgramInfo info) {}
+ public void onCurrentProgramInfoChanged(ProgramInfo info) {
+ dispatch(() -> mClientCb.onCurrentProgramInfoChanged(Convert.programInfoFromHal(info)));
+ }
@Override
public void onProgramListUpdated(ProgramListChunk chunk) {
@@ -61,8 +65,12 @@ class TunerCallback extends ITunerCallback.Stub {
}
@Override
- public void onAntennaStateChange(boolean connected) {}
+ public void onAntennaStateChange(boolean connected) {
+ dispatch(() -> mClientCb.onAntennaState(connected));
+ }
@Override
- public void onParametersUpdated(ArrayList<VendorKeyValue> parameters) {}
+ public void onParametersUpdated(ArrayList<VendorKeyValue> parameters) {
+ dispatch(() -> mClientCb.onParametersUpdated(Convert.vendorInfoFromHal(parameters)));
+ }
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index 1ae7d20fb3fe..8efaa2a53572 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -41,6 +41,7 @@ class TunerSession extends ITuner.Stub {
private final Object mLock = new Object();
+ private final RadioModule mModule;
private final ITunerSession mHwSession;
private final TunerCallback mCallback;
private boolean mIsClosed = false;
@@ -50,7 +51,9 @@ class TunerSession extends ITuner.Stub {
// necessary only for older APIs compatibility
private RadioManager.BandConfig mDummyConfig = null;
- TunerSession(@NonNull ITunerSession hwSession, @NonNull TunerCallback callback) {
+ TunerSession(@NonNull RadioModule module, @NonNull ITunerSession hwSession,
+ @NonNull TunerCallback callback) {
+ mModule = Objects.requireNonNull(module);
mHwSession = Objects.requireNonNull(hwSession);
mCallback = Objects.requireNonNull(callback);
notifyAudioServiceLocked(true);
@@ -128,23 +131,29 @@ class TunerSession extends ITuner.Stub {
}
@Override
- public void step(boolean directionDown, boolean skipSubChannel) {
+ public void step(boolean directionDown, boolean skipSubChannel) throws RemoteException {
synchronized (mLock) {
checkNotClosedLocked();
+ int halResult = mHwSession.step(!directionDown);
+ Convert.throwOnError("step", halResult);
}
}
@Override
- public void scan(boolean directionDown, boolean skipSubChannel) {
+ public void scan(boolean directionDown, boolean skipSubChannel) throws RemoteException {
synchronized (mLock) {
checkNotClosedLocked();
+ int halResult = mHwSession.scan(!directionDown, skipSubChannel);
+ Convert.throwOnError("step", halResult);
}
}
@Override
- public void tune(ProgramSelector selector) {
+ public void tune(ProgramSelector selector) throws RemoteException {
synchronized (mLock) {
checkNotClosedLocked();
+ int halResult = mHwSession.tune(Convert.programSelectorToHal(selector));
+ Convert.throwOnError("tune", halResult);
}
}
@@ -152,36 +161,25 @@ class TunerSession extends ITuner.Stub {
public void cancel() {
synchronized (mLock) {
checkNotClosedLocked();
+ Utils.maybeRethrow(mHwSession::cancel);
}
}
@Override
public void cancelAnnouncement() {
- synchronized (mLock) {
- checkNotClosedLocked();
- }
- }
-
- @Override
- public RadioManager.ProgramInfo getProgramInformation() {
- synchronized (mLock) {
- checkNotClosedLocked();
- return null;
- }
+ Slog.i(TAG, "Announcements control doesn't involve cancelling at the HAL level in 2.x");
}
@Override
public Bitmap getImage(int id) {
- synchronized (mLock) {
- checkNotClosedLocked();
- return null;
- }
+ return mModule.getImage(id);
}
@Override
public boolean startBackgroundScan() {
Slog.i(TAG, "Explicit background scan trigger is not supported with HAL 2.x");
- return false;
+ TunerCallback.dispatch(() -> mCallback.mClientCb.onBackgroundScanComplete());
+ return true;
}
@Override
@@ -240,7 +238,6 @@ class TunerSession extends ITuner.Stub {
Slog.v(TAG, "setConfigFlag " + ConfigFlag.toString(flag) + " = " + value);
synchronized (mLock) {
checkNotClosedLocked();
-
int halResult = mHwSession.setConfigFlag(flag, value);
Convert.throwOnError("setConfigFlag", halResult);
}
@@ -250,7 +247,8 @@ class TunerSession extends ITuner.Stub {
public Map setParameters(Map parameters) {
synchronized (mLock) {
checkNotClosedLocked();
- return null;
+ return Convert.vendorInfoFromHal(Utils.maybeRethrow(
+ () -> mHwSession.setParameters(Convert.vendorInfoToHal(parameters))));
}
}
@@ -258,15 +256,8 @@ class TunerSession extends ITuner.Stub {
public Map getParameters(List<String> keys) {
synchronized (mLock) {
checkNotClosedLocked();
- return null;
- }
- }
-
- @Override
- public boolean isAntennaConnected() {
- synchronized (mLock) {
- checkNotClosedLocked();
- return true;
+ return Convert.vendorInfoFromHal(Utils.maybeRethrow(
+ () -> mHwSession.getParameters(Convert.listToArrayList(keys))));
}
}
}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/Utils.java b/services/core/java/com/android/server/broadcastradio/hal2/Utils.java
index 3520f37880c5..384c9bab94b4 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/Utils.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/Utils.java
@@ -16,6 +16,9 @@
package com.android.server.broadcastradio.hal2;
+import android.annotation.NonNull;
+import android.os.RemoteException;
+
enum FrequencyBand {
UNKNOWN,
FM,
@@ -37,4 +40,29 @@ class Utils {
if (freq < 110000) return FrequencyBand.FM;
return FrequencyBand.UNKNOWN;
}
+
+ interface FuncThrowingRemoteException<T> {
+ T exec() throws RemoteException;
+ }
+
+ static <T> T maybeRethrow(@NonNull FuncThrowingRemoteException<T> r) {
+ try {
+ return r.exec();
+ } catch (RemoteException ex) {
+ ex.rethrowFromSystemServer();
+ return null; // unreachable
+ }
+ }
+
+ interface VoidFuncThrowingRemoteException {
+ void exec() throws RemoteException;
+ }
+
+ static void maybeRethrow(@NonNull VoidFuncThrowingRemoteException r) {
+ try {
+ r.exec();
+ } catch (RemoteException ex) {
+ ex.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp b/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp
index 98921465c673..176ae81a15e4 100644
--- a/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp
+++ b/services/core/jni/BroadcastRadio/BroadcastRadioService.cpp
@@ -249,6 +249,15 @@ static jobject nativeOpenTuner(JNIEnv *env, jobject obj, long nativeContext, jin
Tuner::assignHalInterfaces(env, tuner, module.radioModule, halTuner);
ALOGD("Opened tuner %p", halTuner.get());
+
+ bool isConnected = true;
+ halTuner->getConfiguration([&](Result result, const BandConfig& config) {
+ if (result == Result::OK) isConnected = config.antennaConnected;
+ });
+ if (!isConnected) {
+ tunerCb->antennaStateChange(false);
+ }
+
return tuner.release();
}
diff --git a/services/core/jni/BroadcastRadio/Tuner.cpp b/services/core/jni/BroadcastRadio/Tuner.cpp
index 42eb8739c9e7..42c1332194e1 100644
--- a/services/core/jni/BroadcastRadio/Tuner.cpp
+++ b/services/core/jni/BroadcastRadio/Tuner.cpp
@@ -352,39 +352,6 @@ static void nativeCancelAnnouncement(JNIEnv *env, jobject obj, jlong nativeConte
convert::ThrowIfFailed(env, halTuner->cancelAnnouncement());
}
-static jobject nativeGetProgramInformation(JNIEnv *env, jobject obj, jlong nativeContext) {
- ALOGV("%s", __func__);
- lock_guard<mutex> lk(gContextMutex);
- auto& ctx = getNativeContext(nativeContext);
-
- auto halTuner10 = getHalTuner(ctx);
- auto halTuner11 = ctx.mHalTuner11;
- if (halTuner10 == nullptr) return nullptr;
-
- JavaRef<jobject> jInfo;
- Result halResult;
- Return<void> hidlResult;
- if (halTuner11 != nullptr) {
- hidlResult = halTuner11->getProgramInformation_1_1([&](Result result,
- const V1_1::ProgramInfo& info) {
- halResult = result;
- if (result != Result::OK) return;
- jInfo = convert::ProgramInfoFromHal(env, info);
- });
- } else {
- hidlResult = halTuner10->getProgramInformation([&](Result result,
- const V1_0::ProgramInfo& info) {
- halResult = result;
- if (result != Result::OK) return;
- jInfo = convert::ProgramInfoFromHal(env, info, ctx.mBand);
- });
- }
-
- if (jInfo != nullptr) return jInfo.release();
- convert::ThrowIfFailed(env, hidlResult, halResult);
- return nullptr;
-}
-
static bool nativeStartBackgroundScan(JNIEnv *env, jobject obj, jlong nativeContext) {
ALOGV("%s", __func__);
auto halTuner = getHalTuner11(nativeContext);
@@ -541,21 +508,6 @@ static jobject nativeGetParameters(JNIEnv *env, jobject obj, jlong nativeContext
return jResults.release();
}
-static bool nativeIsAntennaConnected(JNIEnv *env, jobject obj, jlong nativeContext) {
- ALOGV("%s", __func__);
- auto halTuner = getHalTuner(nativeContext);
- if (halTuner == nullptr) return false;
-
- bool isConnected = false;
- Result halResult;
- auto hidlResult = halTuner->getConfiguration([&](Result result, const BandConfig& config) {
- halResult = result;
- isConnected = config.antennaConnected;
- });
- convert::ThrowIfFailed(env, hidlResult, halResult);
- return isConnected;
-}
-
static const JNINativeMethod gTunerMethods[] = {
{ "nativeInit", "(IZI)J", (void*)nativeInit },
{ "nativeFinalize", "(J)V", (void*)nativeFinalize },
@@ -570,8 +522,6 @@ static const JNINativeMethod gTunerMethods[] = {
{ "nativeTune", "(JLandroid/hardware/radio/ProgramSelector;)V", (void*)nativeTune },
{ "nativeCancel", "(J)V", (void*)nativeCancel },
{ "nativeCancelAnnouncement", "(J)V", (void*)nativeCancelAnnouncement },
- { "nativeGetProgramInformation", "(J)Landroid/hardware/radio/RadioManager$ProgramInfo;",
- (void*)nativeGetProgramInformation },
{ "nativeStartBackgroundScan", "(J)Z", (void*)nativeStartBackgroundScan },
{ "nativeGetProgramList", "(JLjava/util/Map;)Ljava/util/List;",
(void*)nativeGetProgramList },
@@ -580,7 +530,6 @@ static const JNINativeMethod gTunerMethods[] = {
{ "nativeSetAnalogForced", "(JZ)V", (void*)nativeSetAnalogForced },
{ "nativeSetParameters", "(JLjava/util/Map;)Ljava/util/Map;", (void*)nativeSetParameters },
{ "nativeGetParameters", "(JLjava/util/List;)Ljava/util/Map;", (void*)nativeGetParameters },
- { "nativeIsAntennaConnected", "(J)Z", (void*)nativeIsAntennaConnected },
};
} // namespace Tuner