From e8f4b34bee319e8b7df6317c08c09319af10b0fe Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Mon, 19 Jun 2017 10:48:16 -0700 Subject: [PATCH] Implement client death monitoring. Bug: b/36863239 Test: one-off integration test (not committed) Change-Id: I0eef3522b62a3ab5d13071c5118026548b3d052c --- .../com/android/server/radio/RadioService.java | 1 - .../core/java/com/android/server/radio/Tuner.java | 15 ++++++++++++++- .../core/jni/com_android_server_radio_Tuner.cpp | 15 ++++++++++++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/radio/RadioService.java b/services/core/java/com/android/server/radio/RadioService.java index 227ea6bdef9b7..87a6fc1ea5cee 100644 --- a/services/core/java/com/android/server/radio/RadioService.java +++ b/services/core/java/com/android/server/radio/RadioService.java @@ -98,7 +98,6 @@ public class RadioService extends SystemService { 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); } } diff --git a/services/core/java/com/android/server/radio/Tuner.java b/services/core/java/com/android/server/radio/Tuner.java index 3c7babd8872b4..5bd7c816943aa 100644 --- a/services/core/java/com/android/server/radio/Tuner.java +++ b/services/core/java/com/android/server/radio/Tuner.java @@ -20,6 +20,8 @@ import android.annotation.NonNull; import android.hardware.radio.ITuner; import android.hardware.radio.ITunerCallback; import android.hardware.radio.RadioManager; +import android.os.IBinder; +import android.os.RemoteException; import android.util.Slog; import java.util.List; @@ -33,18 +35,28 @@ class Tuner extends ITuner.Stub { */ private final long mNativeContext; - @NonNull private final TunerCallback mTunerCallback; private final Object mLock = new Object(); + @NonNull private final TunerCallback mTunerCallback; + @NonNull private final ITunerCallback mClientCallback; + @NonNull private final IBinder.DeathRecipient mDeathRecipient; + private boolean mIsClosed = false; private boolean mIsMuted = false; private int mRegion; // TODO(b/62710330): find better solution to handle regions private final boolean mWithAudio; Tuner(@NonNull ITunerCallback clientCallback, int halRev, int region, boolean withAudio) { + mClientCallback = clientCallback; mTunerCallback = new TunerCallback(this, clientCallback, halRev); mRegion = region; mWithAudio = withAudio; mNativeContext = nativeInit(halRev, withAudio); + mDeathRecipient = this::close; + try { + mClientCallback.asBinder().linkToDeath(mDeathRecipient, 0); + } catch (RemoteException ex) { + close(); + } } @Override @@ -81,6 +93,7 @@ class Tuner extends ITuner.Stub { synchronized (mLock) { if (mIsClosed) return; mTunerCallback.detach(); + mClientCallback.asBinder().unlinkToDeath(mDeathRecipient, 0); nativeClose(mNativeContext); mIsClosed = true; } diff --git a/services/core/jni/com_android_server_radio_Tuner.cpp b/services/core/jni/com_android_server_radio_Tuner.cpp index e6dbfecae44f2..2a712387e3934 100644 --- a/services/core/jni/com_android_server_radio_Tuner.cpp +++ b/services/core/jni/com_android_server_radio_Tuner.cpp @@ -66,6 +66,7 @@ static const char* const kAudioDeviceName = "Radio tuner source"; struct TunerContext { TunerContext() {} + bool mIsClosed = false; HalRevision mHalRev; bool mWithAudio; sp mHalTuner; @@ -127,6 +128,12 @@ void setHalTuner(JNIEnv *env, JavaRef const &jTuner, sp h AutoMutex _l(gContextMutex); auto& ctx = getNativeContext(env, jTuner); + if (ctx.mIsClosed) { + ALOGI("Tuner was closed during initialization"); + // dropping the last reference will close HAL tuner + return; + } + ctx.mHalTuner = halTuner; ctx.mHalTuner11 = V1_1::ITuner::castFrom(halTuner).withDefault(nullptr); ALOGW_IF(ctx.mHalRev >= HalRevision::V1_1 && ctx.mHalTuner11 == nullptr, @@ -159,7 +166,13 @@ 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; + if (ctx.mIsClosed) return; + ctx.mIsClosed = true; + + if (ctx.mHalTuner == nullptr) { + ALOGI("Tuner closed during initialization"); + return; + } ALOGI("Closing tuner %p", ctx.mHalTuner.get()); notifyAudioService(ctx, false);