Loading core/java/android/hardware/radio/ITuner.aidl +7 −0 Original line number Diff line number Diff line Loading @@ -22,5 +22,12 @@ import android.hardware.radio.RadioManager; interface ITuner { void close(); /** * @throws IllegalArgumentException if config is not valid or null */ void setConfiguration(in RadioManager.BandConfig config); RadioManager.BandConfig getConfiguration(); int getProgramInformation(out RadioManager.ProgramInfo[] infoOut); } core/java/android/hardware/radio/TunerAdapter.java +18 −4 Original line number Diff line number Diff line Loading @@ -58,14 +58,28 @@ class TunerAdapter extends RadioTuner { @Override public int setConfiguration(RadioManager.BandConfig config) { // TODO(b/36863239): forward to mTuner throw new RuntimeException("Not implemented"); try { mTuner.setConfiguration(config); return RadioManager.STATUS_OK; } catch (IllegalArgumentException e) { Log.e(TAG, "Can't set configuration", e); return RadioManager.STATUS_BAD_VALUE; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public int getConfiguration(RadioManager.BandConfig[] config) { // TODO(b/36863239): forward to mTuner throw new RuntimeException("Not implemented"); if (config == null || config.length != 1) { throw new IllegalArgumentException("The argument must be an array of length 1"); } try { config[0] = mTuner.getConfiguration(); return RadioManager.STATUS_OK; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override Loading services/core/java/com/android/server/radio/Tuner.java +31 −3 Original line number Diff line number Diff line Loading @@ -31,7 +31,8 @@ class Tuner extends ITuner.Stub { */ private final long mNativeContext; private int mRegion; private final Object mLock = new Object(); private int mRegion; // TODO(b/36863239): find better solution to manage regions Tuner(@NonNull ITunerCallback clientCallback, int region) { mRegion = region; Loading @@ -44,17 +45,44 @@ class Tuner extends ITuner.Stub { super.finalize(); } private native long nativeInit(ITunerCallback clientCallback); private native long nativeInit(@NonNull ITunerCallback clientCallback); private native void nativeFinalize(long nativeContext); private native void nativeClose(long nativeContext); private native void nativeSetConfiguration(long nativeContext, @NonNull RadioManager.BandConfig config); private native RadioManager.BandConfig nativeGetConfiguration(long nativeContext, int region); @Override public void close() { synchronized (mLock) { nativeClose(mNativeContext); } } @Override public void setConfiguration(RadioManager.BandConfig config) { if (config == null) { throw new IllegalArgumentException("The argument must not be a null pointer"); } synchronized (mLock) { nativeSetConfiguration(mNativeContext, config); mRegion = config.getRegion(); } } @Override public RadioManager.BandConfig getConfiguration() { synchronized (mLock) { return nativeGetConfiguration(mNativeContext, mRegion); } } @Override public int getProgramInformation(RadioManager.ProgramInfo[] infoOut) { if (infoOut == null || infoOut.length != 1) { throw new IllegalArgumentException("The argument must be an array of length 1"); } Slog.d(TAG, "getProgramInformation()"); return RadioManager.STATUS_INVALID_OPERATION; } Loading services/core/jni/com_android_server_radio_Tuner.cpp +42 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "com_android_server_radio_Tuner.h" #include "com_android_server_radio_convert.h" #include "com_android_server_radio_Tuner_TunerCallback.h" #include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h> Loading Loading @@ -104,6 +105,13 @@ void setHalTuner(JNIEnv *env, jobject obj, sp<ITuner> halTuner) { ctx.mHalTuner = halTuner; } sp<ITuner> getHalTuner(jlong nativeContext) { AutoMutex _l(gContextMutex); auto tuner = getNativeContext(nativeContext).mHalTuner; LOG_ALWAYS_FATAL_IF(tuner == nullptr, "HAL tuner not set"); return tuner; } sp<ITunerCallback> getNativeCallback(JNIEnv *env, jobject obj) { AutoMutex _l(gContextMutex); auto& ctx = getNativeContext(env, obj); Loading @@ -114,7 +122,7 @@ Region getRegion(JNIEnv *env, jobject obj) { return static_cast<Region>(env->GetIntField(obj, gjni.Tuner.region)); } static void close(JNIEnv *env, jobject obj, jlong nativeContext) { static void nativeClose(JNIEnv *env, jobject obj, jlong nativeContext) { AutoMutex _l(gContextMutex); auto& ctx = getNativeContext(nativeContext); ALOGI("Closing tuner %p", ctx.mHalTuner.get()); Loading @@ -123,10 +131,42 @@ static void close(JNIEnv *env, jobject obj, jlong nativeContext) { ctx.mNativeCallback = nullptr; } static void nativeSetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext, jobject config) { ALOGV("nativeSetConfiguration()"); auto halTuner = getHalTuner(nativeContext); Region region_unused; BandConfig bandConfigHal = convert::BandConfigToHal(env, config, region_unused); convert::ThrowIfFailed(env, halTuner->setConfiguration(bandConfigHal)); } static jobject nativeGetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext, Region region) { ALOGV("nativeSetConfiguration()"); auto halTuner = getHalTuner(nativeContext); BandConfig halConfig; Result halResult; auto hidlResult = halTuner->getConfiguration([&](Result result, const BandConfig& config) { halResult = result; halConfig = config; }); if (convert::ThrowIfFailed(env, hidlResult)) { return nullptr; } return convert::BandConfigFromHal(env, halConfig, region).release(); } static const JNINativeMethod gTunerMethods[] = { { "nativeInit", "(Landroid/hardware/radio/ITunerCallback;)J", (void*)nativeInit }, { "nativeFinalize", "(J)V", (void*)nativeFinalize }, { "nativeClose", "(J)V", (void*)close }, { "nativeClose", "(J)V", (void*)nativeClose }, { "nativeSetConfiguration", "(JLandroid/hardware/radio/RadioManager$BandConfig;)V", (void*)nativeSetConfiguration }, { "nativeGetConfiguration", "(JI)Landroid/hardware/radio/RadioManager$BandConfig;", (void*)nativeGetConfiguration }, }; } // namespace Tuner Loading services/core/jni/com_android_server_radio_convert.cpp +45 −0 Original line number Diff line number Diff line Loading @@ -28,10 +28,12 @@ namespace server { namespace radio { namespace convert { using hardware::Return; using hardware::hidl_vec; using V1_0::Band; using V1_0::Deemphasis; using V1_0::Result; using V1_0::Rds; static struct { Loading Loading @@ -62,6 +64,47 @@ static struct { } BandDescriptor; } gjni; template <typename T> bool ThrowIfFailedCommon(JNIEnv *env, const hardware::Return<T> &hidlResult) { if (hidlResult.isOk()) return false; jniThrowExceptionFmt(env, "java/lang/RuntimeException", "HIDL call failed: %s", hidlResult.description().c_str()); return true; } bool ThrowIfFailed(JNIEnv *env, const hardware::Return<void> &hidlResult) { return ThrowIfFailedCommon(env, hidlResult); } bool ThrowIfFailed(JNIEnv *env, const hardware::Return<V1_0::Result> &hidlResult) { if (ThrowIfFailedCommon(env, hidlResult)) return true; Result result = hidlResult; switch (result) { case Result::OK: return false; case Result::NOT_INITIALIZED: jniThrowException(env, "java/lang/RuntimeException", "Result::NOT_INITIALIZED"); return true; case Result::INVALID_ARGUMENTS: jniThrowException(env, "java/lang/IllegalArgumentException", "Result::INVALID_ARGUMENTS"); return true; case Result::INVALID_STATE: jniThrowException(env, "java/lang/IllegalStateException", "Result::INVALID_STATE"); return true; case Result::TIMEOUT: jniThrowException(env, "java/lang/RuntimeException", "Result::TIMEOUT (unexpected here)"); return true; default: jniThrowExceptionFmt(env, "java/lang/RuntimeException", "Unknown failure, result: %d", result); return true; } } static Rds RdsForRegion(bool rds, Region region) { if (!rds) return Rds::NONE; Loading Loading @@ -95,6 +138,7 @@ static Deemphasis DeemphasisForRegion(Region region) { } JavaRef BandConfigFromHal(JNIEnv *env, const V1_0::BandConfig &config, Region region) { ALOGV("BandConfigFromHal()"); EnvWrapper wrap(env); jint spacing = config.spacings.size() > 0 ? config.spacings[0] : 0; Loading Loading @@ -122,6 +166,7 @@ JavaRef BandConfigFromHal(JNIEnv *env, const V1_0::BandConfig &config, Region re } V1_0::BandConfig BandConfigToHal(JNIEnv *env, jobject jConfig, Region ®ion) { ALOGV("BandConfigToHal()"); auto jDescriptor = env->GetObjectField(jConfig, gjni.BandConfig.descriptor); if (jDescriptor == nullptr) { ALOGE("Descriptor is missing"); Loading Loading
core/java/android/hardware/radio/ITuner.aidl +7 −0 Original line number Diff line number Diff line Loading @@ -22,5 +22,12 @@ import android.hardware.radio.RadioManager; interface ITuner { void close(); /** * @throws IllegalArgumentException if config is not valid or null */ void setConfiguration(in RadioManager.BandConfig config); RadioManager.BandConfig getConfiguration(); int getProgramInformation(out RadioManager.ProgramInfo[] infoOut); }
core/java/android/hardware/radio/TunerAdapter.java +18 −4 Original line number Diff line number Diff line Loading @@ -58,14 +58,28 @@ class TunerAdapter extends RadioTuner { @Override public int setConfiguration(RadioManager.BandConfig config) { // TODO(b/36863239): forward to mTuner throw new RuntimeException("Not implemented"); try { mTuner.setConfiguration(config); return RadioManager.STATUS_OK; } catch (IllegalArgumentException e) { Log.e(TAG, "Can't set configuration", e); return RadioManager.STATUS_BAD_VALUE; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override public int getConfiguration(RadioManager.BandConfig[] config) { // TODO(b/36863239): forward to mTuner throw new RuntimeException("Not implemented"); if (config == null || config.length != 1) { throw new IllegalArgumentException("The argument must be an array of length 1"); } try { config[0] = mTuner.getConfiguration(); return RadioManager.STATUS_OK; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } @Override Loading
services/core/java/com/android/server/radio/Tuner.java +31 −3 Original line number Diff line number Diff line Loading @@ -31,7 +31,8 @@ class Tuner extends ITuner.Stub { */ private final long mNativeContext; private int mRegion; private final Object mLock = new Object(); private int mRegion; // TODO(b/36863239): find better solution to manage regions Tuner(@NonNull ITunerCallback clientCallback, int region) { mRegion = region; Loading @@ -44,17 +45,44 @@ class Tuner extends ITuner.Stub { super.finalize(); } private native long nativeInit(ITunerCallback clientCallback); private native long nativeInit(@NonNull ITunerCallback clientCallback); private native void nativeFinalize(long nativeContext); private native void nativeClose(long nativeContext); private native void nativeSetConfiguration(long nativeContext, @NonNull RadioManager.BandConfig config); private native RadioManager.BandConfig nativeGetConfiguration(long nativeContext, int region); @Override public void close() { synchronized (mLock) { nativeClose(mNativeContext); } } @Override public void setConfiguration(RadioManager.BandConfig config) { if (config == null) { throw new IllegalArgumentException("The argument must not be a null pointer"); } synchronized (mLock) { nativeSetConfiguration(mNativeContext, config); mRegion = config.getRegion(); } } @Override public RadioManager.BandConfig getConfiguration() { synchronized (mLock) { return nativeGetConfiguration(mNativeContext, mRegion); } } @Override public int getProgramInformation(RadioManager.ProgramInfo[] infoOut) { if (infoOut == null || infoOut.length != 1) { throw new IllegalArgumentException("The argument must be an array of length 1"); } Slog.d(TAG, "getProgramInformation()"); return RadioManager.STATUS_INVALID_OPERATION; } Loading
services/core/jni/com_android_server_radio_Tuner.cpp +42 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "com_android_server_radio_Tuner.h" #include "com_android_server_radio_convert.h" #include "com_android_server_radio_Tuner_TunerCallback.h" #include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h> Loading Loading @@ -104,6 +105,13 @@ void setHalTuner(JNIEnv *env, jobject obj, sp<ITuner> halTuner) { ctx.mHalTuner = halTuner; } sp<ITuner> getHalTuner(jlong nativeContext) { AutoMutex _l(gContextMutex); auto tuner = getNativeContext(nativeContext).mHalTuner; LOG_ALWAYS_FATAL_IF(tuner == nullptr, "HAL tuner not set"); return tuner; } sp<ITunerCallback> getNativeCallback(JNIEnv *env, jobject obj) { AutoMutex _l(gContextMutex); auto& ctx = getNativeContext(env, obj); Loading @@ -114,7 +122,7 @@ Region getRegion(JNIEnv *env, jobject obj) { return static_cast<Region>(env->GetIntField(obj, gjni.Tuner.region)); } static void close(JNIEnv *env, jobject obj, jlong nativeContext) { static void nativeClose(JNIEnv *env, jobject obj, jlong nativeContext) { AutoMutex _l(gContextMutex); auto& ctx = getNativeContext(nativeContext); ALOGI("Closing tuner %p", ctx.mHalTuner.get()); Loading @@ -123,10 +131,42 @@ static void close(JNIEnv *env, jobject obj, jlong nativeContext) { ctx.mNativeCallback = nullptr; } static void nativeSetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext, jobject config) { ALOGV("nativeSetConfiguration()"); auto halTuner = getHalTuner(nativeContext); Region region_unused; BandConfig bandConfigHal = convert::BandConfigToHal(env, config, region_unused); convert::ThrowIfFailed(env, halTuner->setConfiguration(bandConfigHal)); } static jobject nativeGetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext, Region region) { ALOGV("nativeSetConfiguration()"); auto halTuner = getHalTuner(nativeContext); BandConfig halConfig; Result halResult; auto hidlResult = halTuner->getConfiguration([&](Result result, const BandConfig& config) { halResult = result; halConfig = config; }); if (convert::ThrowIfFailed(env, hidlResult)) { return nullptr; } return convert::BandConfigFromHal(env, halConfig, region).release(); } static const JNINativeMethod gTunerMethods[] = { { "nativeInit", "(Landroid/hardware/radio/ITunerCallback;)J", (void*)nativeInit }, { "nativeFinalize", "(J)V", (void*)nativeFinalize }, { "nativeClose", "(J)V", (void*)close }, { "nativeClose", "(J)V", (void*)nativeClose }, { "nativeSetConfiguration", "(JLandroid/hardware/radio/RadioManager$BandConfig;)V", (void*)nativeSetConfiguration }, { "nativeGetConfiguration", "(JI)Landroid/hardware/radio/RadioManager$BandConfig;", (void*)nativeGetConfiguration }, }; } // namespace Tuner Loading
services/core/jni/com_android_server_radio_convert.cpp +45 −0 Original line number Diff line number Diff line Loading @@ -28,10 +28,12 @@ namespace server { namespace radio { namespace convert { using hardware::Return; using hardware::hidl_vec; using V1_0::Band; using V1_0::Deemphasis; using V1_0::Result; using V1_0::Rds; static struct { Loading Loading @@ -62,6 +64,47 @@ static struct { } BandDescriptor; } gjni; template <typename T> bool ThrowIfFailedCommon(JNIEnv *env, const hardware::Return<T> &hidlResult) { if (hidlResult.isOk()) return false; jniThrowExceptionFmt(env, "java/lang/RuntimeException", "HIDL call failed: %s", hidlResult.description().c_str()); return true; } bool ThrowIfFailed(JNIEnv *env, const hardware::Return<void> &hidlResult) { return ThrowIfFailedCommon(env, hidlResult); } bool ThrowIfFailed(JNIEnv *env, const hardware::Return<V1_0::Result> &hidlResult) { if (ThrowIfFailedCommon(env, hidlResult)) return true; Result result = hidlResult; switch (result) { case Result::OK: return false; case Result::NOT_INITIALIZED: jniThrowException(env, "java/lang/RuntimeException", "Result::NOT_INITIALIZED"); return true; case Result::INVALID_ARGUMENTS: jniThrowException(env, "java/lang/IllegalArgumentException", "Result::INVALID_ARGUMENTS"); return true; case Result::INVALID_STATE: jniThrowException(env, "java/lang/IllegalStateException", "Result::INVALID_STATE"); return true; case Result::TIMEOUT: jniThrowException(env, "java/lang/RuntimeException", "Result::TIMEOUT (unexpected here)"); return true; default: jniThrowExceptionFmt(env, "java/lang/RuntimeException", "Unknown failure, result: %d", result); return true; } } static Rds RdsForRegion(bool rds, Region region) { if (!rds) return Rds::NONE; Loading Loading @@ -95,6 +138,7 @@ static Deemphasis DeemphasisForRegion(Region region) { } JavaRef BandConfigFromHal(JNIEnv *env, const V1_0::BandConfig &config, Region region) { ALOGV("BandConfigFromHal()"); EnvWrapper wrap(env); jint spacing = config.spacings.size() > 0 ? config.spacings[0] : 0; Loading Loading @@ -122,6 +166,7 @@ JavaRef BandConfigFromHal(JNIEnv *env, const V1_0::BandConfig &config, Region re } V1_0::BandConfig BandConfigToHal(JNIEnv *env, jobject jConfig, Region ®ion) { ALOGV("BandConfigToHal()"); auto jDescriptor = env->GetObjectField(jConfig, gjni.BandConfig.descriptor); if (jDescriptor == nullptr) { ALOGE("Descriptor is missing"); Loading