Loading services/core/java/com/android/server/radio/RadioService.java +6 −2 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ public class RadioService extends SystemService { */ private final long mNativeContext = nativeInit(); private final Object mLock = new Object(); public RadioService(Context context) { super(context); } Loading @@ -61,11 +63,13 @@ public class RadioService extends SystemService { @Override public ITuner openTuner(int moduleId, RadioManager.BandConfig bandConfig, boolean withAudio, ITunerCallback callback) { // TODO(b/36863239): add death monitoring for binder if (callback == null) { throw new IllegalArgumentException("Callback must not be empty"); } synchronized (mLock) { // TODO(b/36863239): add death monitoring for binder return nativeOpenTuner(mNativeContext, moduleId, bandConfig, withAudio, callback); } } } } services/core/java/com/android/server/radio/Tuner.java +23 −2 Original line number Diff line number Diff line Loading @@ -31,15 +31,18 @@ class Tuner extends ITuner.Stub { */ private final long mNativeContext; @NonNull private final TunerCallback mTunerCallback; private final Object mLock = new Object(); private boolean mIsClosed = false; private boolean mIsMuted = false; private int mRegion; // TODO(b/36863239): find better solution to manage regions private final boolean mWithAudio; Tuner(@NonNull ITunerCallback clientCallback, int halRev, int region, boolean withAudio) { mTunerCallback = new TunerCallback(this, clientCallback, halRev); mRegion = region; mWithAudio = withAudio; mNativeContext = nativeInit(clientCallback, halRev); mNativeContext = nativeInit(halRev); } @Override Loading @@ -48,7 +51,7 @@ class Tuner extends ITuner.Stub { super.finalize(); } private native long nativeInit(@NonNull ITunerCallback clientCallback, int halRev); private native long nativeInit(int halRev); private native void nativeFinalize(long nativeContext); private native void nativeClose(long nativeContext); Loading @@ -66,7 +69,16 @@ class Tuner extends ITuner.Stub { @Override public void close() { synchronized (mLock) { if (mIsClosed) return; mTunerCallback.detach(); nativeClose(mNativeContext); mIsClosed = true; } } private void checkNotClosedLocked() { if (mIsClosed) { throw new IllegalStateException("Tuner is closed, no further operations are allowed"); } } Loading @@ -76,6 +88,7 @@ class Tuner extends ITuner.Stub { throw new IllegalArgumentException("The argument must not be a null pointer"); } synchronized (mLock) { checkNotClosedLocked(); nativeSetConfiguration(mNativeContext, config); mRegion = config.getRegion(); } Loading @@ -84,6 +97,7 @@ class Tuner extends ITuner.Stub { @Override public RadioManager.BandConfig getConfiguration() { synchronized (mLock) { checkNotClosedLocked(); return nativeGetConfiguration(mNativeContext, mRegion); } } Loading @@ -94,6 +108,7 @@ class Tuner extends ITuner.Stub { throw new IllegalStateException("Can't operate on mute - no audio requested"); } synchronized (mLock) { checkNotClosedLocked(); if (mIsMuted == mute) return; mIsMuted = mute; Loading @@ -109,6 +124,7 @@ class Tuner extends ITuner.Stub { return true; } synchronized (mLock) { checkNotClosedLocked(); return mIsMuted; } } Loading @@ -116,6 +132,7 @@ class Tuner extends ITuner.Stub { @Override public void step(boolean directionDown, boolean skipSubChannel) { synchronized (mLock) { checkNotClosedLocked(); nativeStep(mNativeContext, directionDown, skipSubChannel); } } Loading @@ -123,6 +140,7 @@ class Tuner extends ITuner.Stub { @Override public void scan(boolean directionDown, boolean skipSubChannel) { synchronized (mLock) { checkNotClosedLocked(); nativeScan(mNativeContext, directionDown, skipSubChannel); } } Loading @@ -130,6 +148,7 @@ class Tuner extends ITuner.Stub { @Override public void tune(int channel, int subChannel) { synchronized (mLock) { checkNotClosedLocked(); nativeTune(mNativeContext, channel, subChannel); } } Loading @@ -137,6 +156,7 @@ class Tuner extends ITuner.Stub { @Override public void cancel() { synchronized (mLock) { checkNotClosedLocked(); nativeCancel(mNativeContext); } } Loading @@ -144,6 +164,7 @@ class Tuner extends ITuner.Stub { @Override public RadioManager.ProgramInfo getProgramInformation() { synchronized (mLock) { checkNotClosedLocked(); return nativeGetProgramInformation(mNativeContext); } } Loading services/core/java/com/android/server/radio/TunerCallback.java 0 → 100644 +97 −0 Original line number Diff line number Diff line /** * Copyright (C) 2017 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 com.android.server.radio; import android.annotation.NonNull; import android.hardware.radio.ITuner; import android.hardware.radio.ITunerCallback; import android.hardware.radio.RadioManager; import android.hardware.radio.RadioTuner; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; class TunerCallback implements ITunerCallback { // TODO(b/36863239): rename to RadioService.TunerCallback when native service goes away private static final String TAG = "RadioServiceJava.TunerCallback"; /** * This field is used by native code, do not access or modify. */ private final long mNativeContext; @NonNull private final Tuner mTuner; @NonNull private final ITunerCallback mClientCallback; TunerCallback(@NonNull Tuner tuner, @NonNull ITunerCallback clientCallback, int halRev) { mTuner = tuner; mClientCallback = clientCallback; mNativeContext = nativeInit(tuner, halRev); } @Override protected void finalize() throws Throwable { nativeFinalize(mNativeContext); super.finalize(); } private native long nativeInit(@NonNull Tuner tuner, int halRev); private native void nativeFinalize(long nativeContext); private native void nativeDetach(long nativeContext); public void detach() { nativeDetach(mNativeContext); } // called from native side private void handleHwFailure() { onError(RadioTuner.ERROR_HARDWARE_FAILURE); mTuner.close(); } @Override public void onError(int status) { try { mClientCallback.onError(status); } catch (RemoteException e) { Slog.e(TAG, "client died", e); } } @Override public void onConfigurationChanged(RadioManager.BandConfig config) { try { mClientCallback.onConfigurationChanged(config); } catch (RemoteException e) { Slog.e(TAG, "client died", e); } } @Override public void onProgramInfoChanged(RadioManager.ProgramInfo info) { try { mClientCallback.onProgramInfoChanged(info); } catch (RemoteException e) { Slog.e(TAG, "client died", e); } } @Override public IBinder asBinder() { throw new RuntimeException("Not a binder"); } } services/core/jni/com_android_server_radio_RadioService.cpp +17 −9 Original line number Diff line number Diff line Loading @@ -49,10 +49,16 @@ using V1_0::ITuner; static Mutex gContextMutex; static jclass gTunerClass; static jmethodID gTunerCstor; static struct { struct { jclass clazz; jmethodID cstor; } Tuner; static jclass gServiceClass; struct { jclass clazz; } RadioService; } gjni; struct ServiceContext { ServiceContext() {} Loading Loading @@ -123,6 +129,8 @@ static sp<V1_0::IBroadcastRadio> getModule(jlong nativeContext) { static jobject nativeOpenTuner(JNIEnv *env, jobject obj, long nativeContext, jint moduleId, jobject bandConfig, bool withAudio, jobject callback) { ALOGV("nativeOpenTuner()"); EnvWrapper wrap(env); if (callback == nullptr) { ALOGE("Callback is empty"); return nullptr; Loading @@ -146,7 +154,8 @@ static jobject nativeOpenTuner(JNIEnv *env, jobject obj, long nativeContext, jin Region region; BandConfig bandConfigHal = convert::BandConfigToHal(env, bandConfig, region); jobject tuner = env->NewObject(gTunerClass, gTunerCstor, callback, halRev, region, withAudio); auto tuner = wrap(env->NewObject(gjni.Tuner.clazz, gjni.Tuner.cstor, callback, halRev, region, withAudio)); if (tuner == nullptr) { ALOGE("Unable to create new tuner object."); return nullptr; Loading @@ -165,13 +174,12 @@ static jobject nativeOpenTuner(JNIEnv *env, jobject obj, long nativeContext, jin ALOGE("Couldn't open tuner"); ALOGE_IF(hidlResult.isOk(), "halResult = %d", halResult); ALOGE_IF(!hidlResult.isOk(), "hidlResult = %s", hidlResult.description().c_str()); env->DeleteLocalRef(tuner); return nullptr; } Tuner::setHalTuner(env, tuner, halTuner); ALOGI("Opened tuner %p", halTuner.get()); return tuner; return tuner.release(); } static const JNINativeMethod gRadioServiceMethods[] = { Loading @@ -192,12 +200,12 @@ void register_android_server_radio_RadioService(JNIEnv *env) { register_android_server_radio_convert(env); auto tunerClass = FindClassOrDie(env, "com/android/server/radio/Tuner"); gTunerClass = MakeGlobalRefOrDie(env, tunerClass); gTunerCstor = GetMethodIDOrDie(env, tunerClass, "<init>", gjni.Tuner.clazz = MakeGlobalRefOrDie(env, tunerClass); gjni.Tuner.cstor = GetMethodIDOrDie(env, tunerClass, "<init>", "(Landroid/hardware/radio/ITunerCallback;IIZ)V"); auto serviceClass = FindClassOrDie(env, "com/android/server/radio/RadioService"); gServiceClass = MakeGlobalRefOrDie(env, serviceClass); gjni.RadioService.clazz = MakeGlobalRefOrDie(env, serviceClass); auto res = jniRegisterNativeMethods(env, "com/android/server/radio/RadioService", gRadioServiceMethods, NELEM(gRadioServiceMethods)); Loading services/core/jni/com_android_server_radio_Tuner.cpp +23 −19 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ static struct { struct { jfieldID nativeContext; jfieldID region; jfieldID tunerCallback; } Tuner; } gjni; Loading @@ -59,7 +60,6 @@ struct TunerContext { HalRevision mHalRev; sp<V1_0::ITuner> mHalTuner; sp<V1_1::ITuner> mHalTuner11; sp<TunerCallback> mNativeCallback; private: DISALLOW_COPY_AND_ASSIGN(TunerContext); Loading @@ -74,17 +74,16 @@ static TunerContext& getNativeContext(jlong nativeContextHandle) { /** * Always lock gContextMutex when using native context. */ static TunerContext& getNativeContext(JNIEnv *env, jobject obj) { return getNativeContext(env->GetLongField(obj, gjni.Tuner.nativeContext)); static TunerContext& getNativeContext(JNIEnv *env, JavaRef<jobject> const &jTuner) { return getNativeContext(env->GetLongField(jTuner.get(), gjni.Tuner.nativeContext)); } static jlong nativeInit(JNIEnv *env, jobject obj, jobject clientCallback, jint halRev) { static jlong nativeInit(JNIEnv *env, jobject obj, jint halRev) { ALOGV("nativeInit()"); AutoMutex _l(gContextMutex); auto ctx = new TunerContext(); ctx->mHalRev = static_cast<HalRevision>(halRev); ctx->mNativeCallback = new TunerCallback(env, obj, clientCallback, ctx->mHalRev); static_assert(sizeof(jlong) >= sizeof(ctx), "jlong is smaller than a pointer"); return reinterpret_cast<jlong>(ctx); Loading @@ -98,12 +97,12 @@ static void nativeFinalize(JNIEnv *env, jobject obj, jlong nativeContext) { delete ctx; } void setHalTuner(JNIEnv *env, jobject obj, sp<V1_0::ITuner> halTuner) { void setHalTuner(JNIEnv *env, JavaRef<jobject> const &jTuner, sp<V1_0::ITuner> halTuner) { ALOGV("setHalTuner(%p)", halTuner.get()); ALOGE_IF(halTuner == nullptr, "HAL tuner is a nullptr"); AutoMutex _l(gContextMutex); auto& ctx = getNativeContext(env, obj); auto& ctx = getNativeContext(env, jTuner); ctx.mHalTuner = halTuner; ctx.mHalTuner11 = V1_1::ITuner::castFrom(halTuner).withDefault(nullptr); Loading @@ -114,21 +113,18 @@ void setHalTuner(JNIEnv *env, jobject obj, sp<V1_0::ITuner> halTuner) { sp<V1_0::ITuner> getHalTuner(jlong nativeContext) { AutoMutex _l(gContextMutex); auto tuner = getNativeContext(nativeContext).mHalTuner; LOG_ALWAYS_FATAL_IF(tuner == nullptr, "HAL tuner not set"); LOG_ALWAYS_FATAL_IF(tuner == nullptr, "HAL tuner is not open"); return tuner; } sp<V1_1::ITuner> getHalTuner11(jlong nativeContext) { AutoMutex _l(gContextMutex); auto tuner = getNativeContext(nativeContext).mHalTuner11; LOG_ALWAYS_FATAL_IF(tuner == nullptr, "HAL tuner not set"); return tuner; return getNativeContext(nativeContext).mHalTuner11; } sp<ITunerCallback> getNativeCallback(JNIEnv *env, jobject obj) { AutoMutex _l(gContextMutex); auto& ctx = getNativeContext(env, obj); return ctx.mNativeCallback; sp<ITunerCallback> getNativeCallback(JNIEnv *env, JavaRef<jobject> const &tuner) { return TunerCallback::getNativeCallback(env, env->GetObjectField(tuner.get(), gjni.Tuner.tunerCallback)); } Region getRegion(JNIEnv *env, jobject obj) { Loading @@ -138,16 +134,16 @@ Region getRegion(JNIEnv *env, jobject obj) { static void nativeClose(JNIEnv *env, jobject obj, jlong nativeContext) { AutoMutex _l(gContextMutex); auto& ctx = getNativeContext(nativeContext); if (ctx.mHalTuner == nullptr) return; ALOGI("Closing tuner %p", ctx.mHalTuner.get()); ctx.mNativeCallback->detach(); ctx.mHalTuner11 = nullptr; ctx.mHalTuner = nullptr; ctx.mNativeCallback = nullptr; } static void nativeSetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext, jobject config) { ALOGV("nativeSetConfiguration()"); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; Region region_unused; BandConfig bandConfigHal = convert::BandConfigToHal(env, config, region_unused); Loading @@ -159,6 +155,7 @@ static jobject nativeGetConfiguration(JNIEnv *env, jobject obj, jlong nativeCont Region region) { ALOGV("nativeSetConfiguration()"); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return nullptr; BandConfig halConfig; Result halResult; Loading @@ -177,6 +174,7 @@ static void nativeStep(JNIEnv *env, jobject obj, jlong nativeContext, bool directionDown, bool skipSubChannel) { ALOGV("nativeStep()"); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; auto dir = convert::DirectionToHal(directionDown); convert::ThrowIfFailed(env, halTuner->step(dir, skipSubChannel)); Loading @@ -186,6 +184,7 @@ static void nativeScan(JNIEnv *env, jobject obj, jlong nativeContext, bool directionDown, bool skipSubChannel) { ALOGV("nativeScan()"); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; auto dir = convert::DirectionToHal(directionDown); convert::ThrowIfFailed(env, halTuner->scan(dir, skipSubChannel)); Loading @@ -195,6 +194,7 @@ static void nativeTune(JNIEnv *env, jobject obj, jlong nativeContext, jint channel, jint subChannel) { ALOGV("nativeTune(%d, %d)", channel, subChannel); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; convert::ThrowIfFailed(env, halTuner->tune(channel, subChannel)); } Loading @@ -202,6 +202,7 @@ static void nativeTune(JNIEnv *env, jobject obj, jlong nativeContext, static void nativeCancel(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeCancel()"); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; convert::ThrowIfFailed(env, halTuner->cancel()); } Loading @@ -210,6 +211,7 @@ static jobject nativeGetProgramInformation(JNIEnv *env, jobject obj, jlong nativ ALOGV("nativeGetProgramInformation()"); auto halTuner10 = getHalTuner(nativeContext); auto halTuner11 = getHalTuner11(nativeContext); if (halTuner10 == nullptr) return nullptr; V1_1::ProgramInfo halInfo; Result halResult; Loading @@ -234,7 +236,7 @@ static jobject nativeGetProgramInformation(JNIEnv *env, jobject obj, jlong nativ } static const JNINativeMethod gTunerMethods[] = { { "nativeInit", "(Landroid/hardware/radio/ITunerCallback;I)J", (void*)nativeInit }, { "nativeInit", "(I)J", (void*)nativeInit }, { "nativeFinalize", "(J)V", (void*)nativeFinalize }, { "nativeClose", "(J)V", (void*)nativeClose }, { "nativeSetConfiguration", "(JLandroid/hardware/radio/RadioManager$BandConfig;)V", Loading @@ -256,11 +258,13 @@ static const JNINativeMethod gTunerMethods[] = { void register_android_server_radio_Tuner(JavaVM *vm, JNIEnv *env) { using namespace server::radio::Tuner; register_android_server_radio_Tuner_TunerCallback(vm, env); register_android_server_radio_TunerCallback(vm, env); auto tunerClass = FindClassOrDie(env, "com/android/server/radio/Tuner"); gjni.Tuner.nativeContext = GetFieldIDOrDie(env, tunerClass, "mNativeContext", "J"); gjni.Tuner.region = GetFieldIDOrDie(env, tunerClass, "mRegion", "I"); gjni.Tuner.tunerCallback = GetFieldIDOrDie(env, tunerClass, "mTunerCallback", "Lcom/android/server/radio/TunerCallback;"); auto res = jniRegisterNativeMethods(env, "com/android/server/radio/Tuner", gTunerMethods, NELEM(gTunerMethods)); Loading Loading
services/core/java/com/android/server/radio/RadioService.java +6 −2 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ public class RadioService extends SystemService { */ private final long mNativeContext = nativeInit(); private final Object mLock = new Object(); public RadioService(Context context) { super(context); } Loading @@ -61,11 +63,13 @@ public class RadioService extends SystemService { @Override public ITuner openTuner(int moduleId, RadioManager.BandConfig bandConfig, boolean withAudio, ITunerCallback callback) { // TODO(b/36863239): add death monitoring for binder if (callback == null) { throw new IllegalArgumentException("Callback must not be empty"); } synchronized (mLock) { // TODO(b/36863239): add death monitoring for binder return nativeOpenTuner(mNativeContext, moduleId, bandConfig, withAudio, callback); } } } }
services/core/java/com/android/server/radio/Tuner.java +23 −2 Original line number Diff line number Diff line Loading @@ -31,15 +31,18 @@ class Tuner extends ITuner.Stub { */ private final long mNativeContext; @NonNull private final TunerCallback mTunerCallback; private final Object mLock = new Object(); private boolean mIsClosed = false; private boolean mIsMuted = false; private int mRegion; // TODO(b/36863239): find better solution to manage regions private final boolean mWithAudio; Tuner(@NonNull ITunerCallback clientCallback, int halRev, int region, boolean withAudio) { mTunerCallback = new TunerCallback(this, clientCallback, halRev); mRegion = region; mWithAudio = withAudio; mNativeContext = nativeInit(clientCallback, halRev); mNativeContext = nativeInit(halRev); } @Override Loading @@ -48,7 +51,7 @@ class Tuner extends ITuner.Stub { super.finalize(); } private native long nativeInit(@NonNull ITunerCallback clientCallback, int halRev); private native long nativeInit(int halRev); private native void nativeFinalize(long nativeContext); private native void nativeClose(long nativeContext); Loading @@ -66,7 +69,16 @@ class Tuner extends ITuner.Stub { @Override public void close() { synchronized (mLock) { if (mIsClosed) return; mTunerCallback.detach(); nativeClose(mNativeContext); mIsClosed = true; } } private void checkNotClosedLocked() { if (mIsClosed) { throw new IllegalStateException("Tuner is closed, no further operations are allowed"); } } Loading @@ -76,6 +88,7 @@ class Tuner extends ITuner.Stub { throw new IllegalArgumentException("The argument must not be a null pointer"); } synchronized (mLock) { checkNotClosedLocked(); nativeSetConfiguration(mNativeContext, config); mRegion = config.getRegion(); } Loading @@ -84,6 +97,7 @@ class Tuner extends ITuner.Stub { @Override public RadioManager.BandConfig getConfiguration() { synchronized (mLock) { checkNotClosedLocked(); return nativeGetConfiguration(mNativeContext, mRegion); } } Loading @@ -94,6 +108,7 @@ class Tuner extends ITuner.Stub { throw new IllegalStateException("Can't operate on mute - no audio requested"); } synchronized (mLock) { checkNotClosedLocked(); if (mIsMuted == mute) return; mIsMuted = mute; Loading @@ -109,6 +124,7 @@ class Tuner extends ITuner.Stub { return true; } synchronized (mLock) { checkNotClosedLocked(); return mIsMuted; } } Loading @@ -116,6 +132,7 @@ class Tuner extends ITuner.Stub { @Override public void step(boolean directionDown, boolean skipSubChannel) { synchronized (mLock) { checkNotClosedLocked(); nativeStep(mNativeContext, directionDown, skipSubChannel); } } Loading @@ -123,6 +140,7 @@ class Tuner extends ITuner.Stub { @Override public void scan(boolean directionDown, boolean skipSubChannel) { synchronized (mLock) { checkNotClosedLocked(); nativeScan(mNativeContext, directionDown, skipSubChannel); } } Loading @@ -130,6 +148,7 @@ class Tuner extends ITuner.Stub { @Override public void tune(int channel, int subChannel) { synchronized (mLock) { checkNotClosedLocked(); nativeTune(mNativeContext, channel, subChannel); } } Loading @@ -137,6 +156,7 @@ class Tuner extends ITuner.Stub { @Override public void cancel() { synchronized (mLock) { checkNotClosedLocked(); nativeCancel(mNativeContext); } } Loading @@ -144,6 +164,7 @@ class Tuner extends ITuner.Stub { @Override public RadioManager.ProgramInfo getProgramInformation() { synchronized (mLock) { checkNotClosedLocked(); return nativeGetProgramInformation(mNativeContext); } } Loading
services/core/java/com/android/server/radio/TunerCallback.java 0 → 100644 +97 −0 Original line number Diff line number Diff line /** * Copyright (C) 2017 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 com.android.server.radio; import android.annotation.NonNull; import android.hardware.radio.ITuner; import android.hardware.radio.ITunerCallback; import android.hardware.radio.RadioManager; import android.hardware.radio.RadioTuner; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; class TunerCallback implements ITunerCallback { // TODO(b/36863239): rename to RadioService.TunerCallback when native service goes away private static final String TAG = "RadioServiceJava.TunerCallback"; /** * This field is used by native code, do not access or modify. */ private final long mNativeContext; @NonNull private final Tuner mTuner; @NonNull private final ITunerCallback mClientCallback; TunerCallback(@NonNull Tuner tuner, @NonNull ITunerCallback clientCallback, int halRev) { mTuner = tuner; mClientCallback = clientCallback; mNativeContext = nativeInit(tuner, halRev); } @Override protected void finalize() throws Throwable { nativeFinalize(mNativeContext); super.finalize(); } private native long nativeInit(@NonNull Tuner tuner, int halRev); private native void nativeFinalize(long nativeContext); private native void nativeDetach(long nativeContext); public void detach() { nativeDetach(mNativeContext); } // called from native side private void handleHwFailure() { onError(RadioTuner.ERROR_HARDWARE_FAILURE); mTuner.close(); } @Override public void onError(int status) { try { mClientCallback.onError(status); } catch (RemoteException e) { Slog.e(TAG, "client died", e); } } @Override public void onConfigurationChanged(RadioManager.BandConfig config) { try { mClientCallback.onConfigurationChanged(config); } catch (RemoteException e) { Slog.e(TAG, "client died", e); } } @Override public void onProgramInfoChanged(RadioManager.ProgramInfo info) { try { mClientCallback.onProgramInfoChanged(info); } catch (RemoteException e) { Slog.e(TAG, "client died", e); } } @Override public IBinder asBinder() { throw new RuntimeException("Not a binder"); } }
services/core/jni/com_android_server_radio_RadioService.cpp +17 −9 Original line number Diff line number Diff line Loading @@ -49,10 +49,16 @@ using V1_0::ITuner; static Mutex gContextMutex; static jclass gTunerClass; static jmethodID gTunerCstor; static struct { struct { jclass clazz; jmethodID cstor; } Tuner; static jclass gServiceClass; struct { jclass clazz; } RadioService; } gjni; struct ServiceContext { ServiceContext() {} Loading Loading @@ -123,6 +129,8 @@ static sp<V1_0::IBroadcastRadio> getModule(jlong nativeContext) { static jobject nativeOpenTuner(JNIEnv *env, jobject obj, long nativeContext, jint moduleId, jobject bandConfig, bool withAudio, jobject callback) { ALOGV("nativeOpenTuner()"); EnvWrapper wrap(env); if (callback == nullptr) { ALOGE("Callback is empty"); return nullptr; Loading @@ -146,7 +154,8 @@ static jobject nativeOpenTuner(JNIEnv *env, jobject obj, long nativeContext, jin Region region; BandConfig bandConfigHal = convert::BandConfigToHal(env, bandConfig, region); jobject tuner = env->NewObject(gTunerClass, gTunerCstor, callback, halRev, region, withAudio); auto tuner = wrap(env->NewObject(gjni.Tuner.clazz, gjni.Tuner.cstor, callback, halRev, region, withAudio)); if (tuner == nullptr) { ALOGE("Unable to create new tuner object."); return nullptr; Loading @@ -165,13 +174,12 @@ static jobject nativeOpenTuner(JNIEnv *env, jobject obj, long nativeContext, jin ALOGE("Couldn't open tuner"); ALOGE_IF(hidlResult.isOk(), "halResult = %d", halResult); ALOGE_IF(!hidlResult.isOk(), "hidlResult = %s", hidlResult.description().c_str()); env->DeleteLocalRef(tuner); return nullptr; } Tuner::setHalTuner(env, tuner, halTuner); ALOGI("Opened tuner %p", halTuner.get()); return tuner; return tuner.release(); } static const JNINativeMethod gRadioServiceMethods[] = { Loading @@ -192,12 +200,12 @@ void register_android_server_radio_RadioService(JNIEnv *env) { register_android_server_radio_convert(env); auto tunerClass = FindClassOrDie(env, "com/android/server/radio/Tuner"); gTunerClass = MakeGlobalRefOrDie(env, tunerClass); gTunerCstor = GetMethodIDOrDie(env, tunerClass, "<init>", gjni.Tuner.clazz = MakeGlobalRefOrDie(env, tunerClass); gjni.Tuner.cstor = GetMethodIDOrDie(env, tunerClass, "<init>", "(Landroid/hardware/radio/ITunerCallback;IIZ)V"); auto serviceClass = FindClassOrDie(env, "com/android/server/radio/RadioService"); gServiceClass = MakeGlobalRefOrDie(env, serviceClass); gjni.RadioService.clazz = MakeGlobalRefOrDie(env, serviceClass); auto res = jniRegisterNativeMethods(env, "com/android/server/radio/RadioService", gRadioServiceMethods, NELEM(gRadioServiceMethods)); Loading
services/core/jni/com_android_server_radio_Tuner.cpp +23 −19 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ static struct { struct { jfieldID nativeContext; jfieldID region; jfieldID tunerCallback; } Tuner; } gjni; Loading @@ -59,7 +60,6 @@ struct TunerContext { HalRevision mHalRev; sp<V1_0::ITuner> mHalTuner; sp<V1_1::ITuner> mHalTuner11; sp<TunerCallback> mNativeCallback; private: DISALLOW_COPY_AND_ASSIGN(TunerContext); Loading @@ -74,17 +74,16 @@ static TunerContext& getNativeContext(jlong nativeContextHandle) { /** * Always lock gContextMutex when using native context. */ static TunerContext& getNativeContext(JNIEnv *env, jobject obj) { return getNativeContext(env->GetLongField(obj, gjni.Tuner.nativeContext)); static TunerContext& getNativeContext(JNIEnv *env, JavaRef<jobject> const &jTuner) { return getNativeContext(env->GetLongField(jTuner.get(), gjni.Tuner.nativeContext)); } static jlong nativeInit(JNIEnv *env, jobject obj, jobject clientCallback, jint halRev) { static jlong nativeInit(JNIEnv *env, jobject obj, jint halRev) { ALOGV("nativeInit()"); AutoMutex _l(gContextMutex); auto ctx = new TunerContext(); ctx->mHalRev = static_cast<HalRevision>(halRev); ctx->mNativeCallback = new TunerCallback(env, obj, clientCallback, ctx->mHalRev); static_assert(sizeof(jlong) >= sizeof(ctx), "jlong is smaller than a pointer"); return reinterpret_cast<jlong>(ctx); Loading @@ -98,12 +97,12 @@ static void nativeFinalize(JNIEnv *env, jobject obj, jlong nativeContext) { delete ctx; } void setHalTuner(JNIEnv *env, jobject obj, sp<V1_0::ITuner> halTuner) { void setHalTuner(JNIEnv *env, JavaRef<jobject> const &jTuner, sp<V1_0::ITuner> halTuner) { ALOGV("setHalTuner(%p)", halTuner.get()); ALOGE_IF(halTuner == nullptr, "HAL tuner is a nullptr"); AutoMutex _l(gContextMutex); auto& ctx = getNativeContext(env, obj); auto& ctx = getNativeContext(env, jTuner); ctx.mHalTuner = halTuner; ctx.mHalTuner11 = V1_1::ITuner::castFrom(halTuner).withDefault(nullptr); Loading @@ -114,21 +113,18 @@ void setHalTuner(JNIEnv *env, jobject obj, sp<V1_0::ITuner> halTuner) { sp<V1_0::ITuner> getHalTuner(jlong nativeContext) { AutoMutex _l(gContextMutex); auto tuner = getNativeContext(nativeContext).mHalTuner; LOG_ALWAYS_FATAL_IF(tuner == nullptr, "HAL tuner not set"); LOG_ALWAYS_FATAL_IF(tuner == nullptr, "HAL tuner is not open"); return tuner; } sp<V1_1::ITuner> getHalTuner11(jlong nativeContext) { AutoMutex _l(gContextMutex); auto tuner = getNativeContext(nativeContext).mHalTuner11; LOG_ALWAYS_FATAL_IF(tuner == nullptr, "HAL tuner not set"); return tuner; return getNativeContext(nativeContext).mHalTuner11; } sp<ITunerCallback> getNativeCallback(JNIEnv *env, jobject obj) { AutoMutex _l(gContextMutex); auto& ctx = getNativeContext(env, obj); return ctx.mNativeCallback; sp<ITunerCallback> getNativeCallback(JNIEnv *env, JavaRef<jobject> const &tuner) { return TunerCallback::getNativeCallback(env, env->GetObjectField(tuner.get(), gjni.Tuner.tunerCallback)); } Region getRegion(JNIEnv *env, jobject obj) { Loading @@ -138,16 +134,16 @@ Region getRegion(JNIEnv *env, jobject obj) { static void nativeClose(JNIEnv *env, jobject obj, jlong nativeContext) { AutoMutex _l(gContextMutex); auto& ctx = getNativeContext(nativeContext); if (ctx.mHalTuner == nullptr) return; ALOGI("Closing tuner %p", ctx.mHalTuner.get()); ctx.mNativeCallback->detach(); ctx.mHalTuner11 = nullptr; ctx.mHalTuner = nullptr; ctx.mNativeCallback = nullptr; } static void nativeSetConfiguration(JNIEnv *env, jobject obj, jlong nativeContext, jobject config) { ALOGV("nativeSetConfiguration()"); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; Region region_unused; BandConfig bandConfigHal = convert::BandConfigToHal(env, config, region_unused); Loading @@ -159,6 +155,7 @@ static jobject nativeGetConfiguration(JNIEnv *env, jobject obj, jlong nativeCont Region region) { ALOGV("nativeSetConfiguration()"); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return nullptr; BandConfig halConfig; Result halResult; Loading @@ -177,6 +174,7 @@ static void nativeStep(JNIEnv *env, jobject obj, jlong nativeContext, bool directionDown, bool skipSubChannel) { ALOGV("nativeStep()"); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; auto dir = convert::DirectionToHal(directionDown); convert::ThrowIfFailed(env, halTuner->step(dir, skipSubChannel)); Loading @@ -186,6 +184,7 @@ static void nativeScan(JNIEnv *env, jobject obj, jlong nativeContext, bool directionDown, bool skipSubChannel) { ALOGV("nativeScan()"); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; auto dir = convert::DirectionToHal(directionDown); convert::ThrowIfFailed(env, halTuner->scan(dir, skipSubChannel)); Loading @@ -195,6 +194,7 @@ static void nativeTune(JNIEnv *env, jobject obj, jlong nativeContext, jint channel, jint subChannel) { ALOGV("nativeTune(%d, %d)", channel, subChannel); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; convert::ThrowIfFailed(env, halTuner->tune(channel, subChannel)); } Loading @@ -202,6 +202,7 @@ static void nativeTune(JNIEnv *env, jobject obj, jlong nativeContext, static void nativeCancel(JNIEnv *env, jobject obj, jlong nativeContext) { ALOGV("nativeCancel()"); auto halTuner = getHalTuner(nativeContext); if (halTuner == nullptr) return; convert::ThrowIfFailed(env, halTuner->cancel()); } Loading @@ -210,6 +211,7 @@ static jobject nativeGetProgramInformation(JNIEnv *env, jobject obj, jlong nativ ALOGV("nativeGetProgramInformation()"); auto halTuner10 = getHalTuner(nativeContext); auto halTuner11 = getHalTuner11(nativeContext); if (halTuner10 == nullptr) return nullptr; V1_1::ProgramInfo halInfo; Result halResult; Loading @@ -234,7 +236,7 @@ static jobject nativeGetProgramInformation(JNIEnv *env, jobject obj, jlong nativ } static const JNINativeMethod gTunerMethods[] = { { "nativeInit", "(Landroid/hardware/radio/ITunerCallback;I)J", (void*)nativeInit }, { "nativeInit", "(I)J", (void*)nativeInit }, { "nativeFinalize", "(J)V", (void*)nativeFinalize }, { "nativeClose", "(J)V", (void*)nativeClose }, { "nativeSetConfiguration", "(JLandroid/hardware/radio/RadioManager$BandConfig;)V", Loading @@ -256,11 +258,13 @@ static const JNINativeMethod gTunerMethods[] = { void register_android_server_radio_Tuner(JavaVM *vm, JNIEnv *env) { using namespace server::radio::Tuner; register_android_server_radio_Tuner_TunerCallback(vm, env); register_android_server_radio_TunerCallback(vm, env); auto tunerClass = FindClassOrDie(env, "com/android/server/radio/Tuner"); gjni.Tuner.nativeContext = GetFieldIDOrDie(env, tunerClass, "mNativeContext", "J"); gjni.Tuner.region = GetFieldIDOrDie(env, tunerClass, "mRegion", "I"); gjni.Tuner.tunerCallback = GetFieldIDOrDie(env, tunerClass, "mTunerCallback", "Lcom/android/server/radio/TunerCallback;"); auto res = jniRegisterNativeMethods(env, "com/android/server/radio/Tuner", gTunerMethods, NELEM(gTunerMethods)); Loading