Merge "Tuner JNI: Dvr and DvrCallback" into rvc-dev
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 894882f..d4494acb7e 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -906,6 +906,7 @@
         Objects.requireNonNull(l, "OnRecordStatusChangedListener must not be null");
         checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX);
         DvrRecorder dvr = nativeOpenDvrRecorder(bufferSize);
+        dvr.setListener(executor, l);
         return dvr;
     }
 
@@ -928,6 +929,7 @@
         Objects.requireNonNull(l, "OnPlaybackStatusChangedListener must not be null");
         checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX);
         DvrPlayback dvr = nativeOpenDvrPlayback(bufferSize);
+        dvr.setListener(executor, l);
         return dvr;
     }
 
diff --git a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
index 0d10d94..9971c84 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
@@ -21,12 +21,15 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.hardware.tv.tuner.V1_0.Constants;
+import android.media.tv.tuner.Tuner;
 import android.media.tv.tuner.Tuner.Result;
+import android.media.tv.tuner.TunerUtils;
 import android.media.tv.tuner.filter.Filter;
 import android.os.ParcelFileDescriptor;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
 
 /**
  * Digital Video Record (DVR) class which provides playback control on Demux's input buffer.
@@ -70,6 +73,8 @@
     public static final int PLAYBACK_STATUS_FULL = Constants.PlaybackStatus.SPACE_FULL;
 
     private long mNativeContext;
+    private OnPlaybackStatusChangedListener mListener;
+    private Executor mExecutor;
 
     private native int nativeAttachFilter(Filter filter);
     private native int nativeDetachFilter(Filter filter);
@@ -85,6 +90,19 @@
     private DvrPlayback() {
     }
 
+    /** @hide */
+    public void setListener(
+            @NonNull Executor executor, @NonNull OnPlaybackStatusChangedListener listener) {
+        mExecutor = executor;
+        mListener = listener;
+    }
+
+    private void onPlaybackStatusChanged(int status) {
+        if (mExecutor != null && mListener != null) {
+            mExecutor.execute(() -> mListener.onPlaybackStatusChanged(status));
+        }
+    }
+
 
     /**
      * Attaches a filter to DVR interface for recording.
@@ -164,7 +182,10 @@
      */
     @Override
     public void close() {
-        nativeClose();
+        int res = nativeClose();
+        if (res != Tuner.RESULT_SUCCESS) {
+            TunerUtils.throwExceptionForResult(res, "failed to close DVR playback");
+        }
     }
 
     /**
diff --git a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
index dbda7bb..198bd0f 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
@@ -19,10 +19,14 @@
 import android.annotation.BytesLong;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.media.tv.tuner.Tuner;
 import android.media.tv.tuner.Tuner.Result;
+import android.media.tv.tuner.TunerUtils;
 import android.media.tv.tuner.filter.Filter;
 import android.os.ParcelFileDescriptor;
 
+import java.util.concurrent.Executor;
+
 /**
  * Digital Video Record (DVR) recorder class which provides record control on Demux's output buffer.
  *
@@ -31,6 +35,8 @@
 @SystemApi
 public class DvrRecorder implements AutoCloseable {
     private long mNativeContext;
+    private OnRecordStatusChangedListener mListener;
+    private Executor mExecutor;
 
     private native int nativeAttachFilter(Filter filter);
     private native int nativeDetachFilter(Filter filter);
@@ -46,6 +52,19 @@
     private DvrRecorder() {
     }
 
+    /** @hide */
+    public void setListener(
+            @NonNull Executor executor, @NonNull OnRecordStatusChangedListener listener) {
+        mExecutor = executor;
+        mListener = listener;
+    }
+
+    private void onRecordStatusChanged(int status) {
+        if (mExecutor != null && mListener != null) {
+            mExecutor.execute(() -> mListener.onRecordStatusChanged(status));
+        }
+    }
+
 
     /**
      * Attaches a filter to DVR interface for recording.
@@ -125,7 +144,10 @@
      */
     @Override
     public void close() {
-        nativeClose();
+        int res = nativeClose();
+        if (res != Tuner.RESULT_SUCCESS) {
+            TunerUtils.throwExceptionForResult(res, "failed to close DVR recorder");
+        }
     }
 
     /**
@@ -163,6 +185,10 @@
      */
     @BytesLong
     public long write(@NonNull byte[] bytes, @BytesLong long offset, @BytesLong long size) {
+        if (size + offset > bytes.length) {
+            throw new ArrayIndexOutOfBoundsException(
+                    "Array length=" + bytes.length + ", offset=" + offset + ", size=" + size);
+        }
         return nativeWrite(bytes, offset, size);
     }
 }
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 9310d38..4a7e8e1 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -151,6 +151,8 @@
     jmethodID onFilterEventID;
     jmethodID lnbInitID;
     jmethodID onLnbEventID;
+    jmethodID onDvrRecordStatusID;
+    jmethodID onDvrPlaybackStatusID;
     jmethodID descramblerInitID;
     jmethodID linearBlockInitID;
     jmethodID linearBlockSetInternalStateID;
@@ -198,13 +200,23 @@
 }
 
 /////////////// DvrCallback ///////////////////////
-Return<void> DvrCallback::onRecordStatus(RecordStatus /*status*/) {
+Return<void> DvrCallback::onRecordStatus(RecordStatus status) {
     ALOGD("DvrCallback::onRecordStatus");
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(
+            mDvr,
+            gFields.onDvrRecordStatusID,
+            (jint) status);
     return Void();
 }
 
-Return<void> DvrCallback::onPlaybackStatus(PlaybackStatus /*status*/) {
+Return<void> DvrCallback::onPlaybackStatus(PlaybackStatus status) {
     ALOGD("DvrCallback::onPlaybackStatus");
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    env->CallVoidMethod(
+            mDvr,
+            gFields.onDvrPlaybackStatusID,
+            (jint) status);
     return Void();
 }
 
@@ -214,27 +226,40 @@
     mDvr = env->NewWeakGlobalRef(dvr);
 }
 
-/////////////// Dvr ///////////////////////
-
-Dvr::Dvr(sp<IDvr> sp, jweak obj) : mDvrSp(sp), mDvrObj(obj), mDvrMQEventFlag(nullptr) {}
-
-Dvr::~Dvr() {
-    EventFlag::deleteEventFlag(&mDvrMQEventFlag);
+DvrCallback::~DvrCallback() {
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    if (mDvr != NULL) {
+        env->DeleteWeakGlobalRef(mDvr);
+        mDvr = NULL;
+    }
 }
 
-int Dvr::close() {
+/////////////// Dvr ///////////////////////
+
+Dvr::Dvr(sp<IDvr> sp, jobject obj) : mDvrSp(sp), mDvrMQEventFlag(nullptr) {
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    mDvrObj = env->NewWeakGlobalRef(obj);
+}
+
+Dvr::~Dvr() {
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    env->DeleteWeakGlobalRef(mDvrObj);
+    mDvrObj = NULL;
+}
+
+jint Dvr::close() {
     Result r = mDvrSp->close();
     if (r == Result::SUCCESS) {
         EventFlag::deleteEventFlag(&mDvrMQEventFlag);
     }
-    return (int)r;
+    return (jint) r;
 }
 
 sp<IDvr> Dvr::getIDvr() {
     return mDvrSp;
 }
 
-DvrMQ& Dvr::getDvrMQ() {
+MQ& Dvr::getDvrMQ() {
     return *mDvrMQ;
 }
 
@@ -558,6 +583,14 @@
     mFilter = env->NewWeakGlobalRef(filter);
 }
 
+FilterCallback::~FilterCallback() {
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    if (mFilter != NULL) {
+        env->DeleteWeakGlobalRef(mFilter);
+        mFilter = NULL;
+    }
+}
+
 /////////////// Filter ///////////////////////
 
 Filter::Filter(sp<IFilter> sp, jobject obj) : mFilterSp(sp) {
@@ -785,6 +818,7 @@
 JTuner::~JTuner() {
     JNIEnv *env = AndroidRuntime::getJNIEnv();
 
+    env->DeleteWeakGlobalRef(mObject);
     env->DeleteGlobalRef(mClass);
     mTuner = NULL;
     mClass = NULL;
@@ -1988,10 +2022,14 @@
     jclass dvrRecorderClazz = env->FindClass("android/media/tv/tuner/dvr/DvrRecorder");
     gFields.dvrRecorderContext = env->GetFieldID(dvrRecorderClazz, "mNativeContext", "J");
     gFields.dvrRecorderInitID = env->GetMethodID(dvrRecorderClazz, "<init>", "()V");
+    gFields.onDvrRecordStatusID =
+            env->GetMethodID(dvrRecorderClazz, "onRecordStatusChanged", "(I)V");
 
     jclass dvrPlaybackClazz = env->FindClass("android/media/tv/tuner/dvr/DvrPlayback");
     gFields.dvrPlaybackContext = env->GetFieldID(dvrPlaybackClazz, "mNativeContext", "J");
     gFields.dvrPlaybackInitID = env->GetMethodID(dvrPlaybackClazz, "<init>", "()V");
+    gFields.onDvrPlaybackStatusID =
+            env->GetMethodID(dvrRecorderClazz, "onPlaybackStatusChanged", "(I)V");
 
     jclass linearBlockClazz = env->FindClass("android/media/MediaCodec$LinearBlock");
     gFields.linearBlockInitID = env->GetMethodID(linearBlockClazz, "<init>", "()V");
@@ -2485,10 +2523,11 @@
     return filterSettings;
 }
 
-static jint copyData(JNIEnv *env, sp<Filter> filter, jbyteArray buffer, jlong offset, jlong size) {
+static jint copyData(JNIEnv *env, std::unique_ptr<MQ>& mq, EventFlag* flag, jbyteArray buffer,
+        jlong offset, jlong size) {
     ALOGD("copyData, size=%ld, offset=%ld", (long) size, (long) offset);
 
-    jlong available = filter->mFilterMQ->availableToRead();
+    jlong available = mq->availableToRead();
     ALOGD("copyData, available=%ld", (long) available);
     size = std::min(size, available);
 
@@ -2500,9 +2539,9 @@
         return 0;
     }
 
-    if (filter->mFilterMQ->read(reinterpret_cast<unsigned char*>(dst) + offset, size)) {
+    if (mq->read(reinterpret_cast<unsigned char*>(dst) + offset, size)) {
         env->ReleaseByteArrayElements(buffer, dst, 0);
-        filter->mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
+        flag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
     } else {
         ALOGD("Failed to read FMQ");
         env->ReleaseByteArrayElements(buffer, dst, 0);
@@ -2537,7 +2576,7 @@
                     ALOGD("getFilterQueueDesc");
                 });
         if (getQueueDescResult == Result::SUCCESS) {
-            filterSp->mFilterMQ = std::make_unique<FilterMQ>(filterMQDesc, true);
+            filterSp->mFilterMQ = std::make_unique<MQ>(filterMQDesc, true);
             EventFlag::createEventFlag(
                     filterSp->mFilterMQ->getEventFlagWord(), &(filterSp->mFilterMQEventFlag));
         }
@@ -2622,7 +2661,7 @@
         ALOGD("Failed to read filter FMQ: filter not found");
         return (jint) Result::INVALID_STATE;
     }
-    return copyData(env, filterSp, buffer, offset, size);
+    return copyData(env, filterSp->mFilterMQ, filterSp->mFilterMQEventFlag, buffer, offset, size);
 }
 
 static jint android_media_tv_Tuner_close_filter(JNIEnv *env, jobject filter) {
@@ -2781,86 +2820,103 @@
     return tuner->getDemuxCaps();
 }
 
-static int android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) {
-    sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
-    sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
-    if (dvrSp == NULL || iFilterSp == NULL) {
-        return false;
-    }
-    Result result = dvrSp->attachFilter(iFilterSp);
-    return (int) result;
-}
-
-static int android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) {
-    sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
-    sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
-    if (dvrSp == NULL || iFilterSp == NULL) {
-        return false;
-    }
-    Result result = dvrSp->detachFilter(iFilterSp);
-    return (int) result;
-}
-
-static int android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) {
+static jint android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) {
     sp<Dvr> dvrSp = getDvr(env, dvr);
+    if (dvrSp == NULL) {
+        return (jint) Result::NOT_INITIALIZED;
+    }
+    sp<Filter> filterSp = getFilter(env, filter);
+    if (filterSp == NULL) {
+        return (jint) Result::INVALID_ARGUMENT;
+    }
     sp<IDvr> iDvrSp = dvrSp->getIDvr();
+    sp<IFilter> iFilterSp = filterSp->getIFilter();
+    Result result = iDvrSp->attachFilter(iFilterSp);
+    return (jint) result;
+}
+
+static jint android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) {
+    sp<Dvr> dvrSp = getDvr(env, dvr);
+    if (dvrSp == NULL) {
+        return (jint) Result::NOT_INITIALIZED;
+    }
+    sp<Filter> filterSp = getFilter(env, filter);
+    if (filterSp == NULL) {
+        return (jint) Result::INVALID_ARGUMENT;
+    }
+    sp<IDvr> iDvrSp = dvrSp->getIDvr();
+    sp<IFilter> iFilterSp = filterSp->getIFilter();
+    Result result = iDvrSp->detachFilter(iFilterSp);
+    return (jint) result;
+}
+
+static jint android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) {
+    sp<Dvr> dvrSp = getDvr(env, dvr);
     if (dvrSp == NULL) {
         ALOGD("Failed to configure dvr: dvr not found");
-        return (int)Result::INVALID_STATE;
+        return (int)Result::NOT_INITIALIZED;
     }
+    sp<IDvr> iDvrSp = dvrSp->getIDvr();
     Result result = iDvrSp->configure(getDvrSettings(env, settings));
-    MQDescriptorSync<uint8_t> dvrMQDesc;
-    if (result == Result::SUCCESS) {
-        Result getQueueDescResult = Result::UNKNOWN_ERROR;
-        iDvrSp->getQueueDesc(
-                [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
-                    dvrMQDesc = desc;
-                    getQueueDescResult = r;
-                    ALOGD("getDvrQueueDesc");
-                });
-        if (getQueueDescResult == Result::SUCCESS) {
-            dvrSp->mDvrMQ = std::make_unique<DvrMQ>(dvrMQDesc, true);
-            EventFlag::createEventFlag(
-                    dvrSp->mDvrMQ->getEventFlagWord(), &(dvrSp->mDvrMQEventFlag));
-        }
+    if (result != Result::SUCCESS) {
+        return (jint) result;
     }
-    return (int)result;
+    MQDescriptorSync<uint8_t> dvrMQDesc;
+    Result getQueueDescResult = Result::UNKNOWN_ERROR;
+    iDvrSp->getQueueDesc(
+            [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
+                dvrMQDesc = desc;
+                getQueueDescResult = r;
+                ALOGD("getDvrQueueDesc");
+            });
+    if (getQueueDescResult == Result::SUCCESS) {
+        dvrSp->mDvrMQ = std::make_unique<MQ>(dvrMQDesc, true);
+        EventFlag::createEventFlag(
+                dvrSp->mDvrMQ->getEventFlagWord(), &(dvrSp->mDvrMQEventFlag));
+    }
+    return (jint) getQueueDescResult;
 }
 
-static int android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) {
-
-    sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
+static jint android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) {
+    sp<Dvr> dvrSp = getDvr(env, dvr);
     if (dvrSp == NULL) {
         ALOGD("Failed to start dvr: dvr not found");
-        return false;
+        return (jint) Result::NOT_INITIALIZED;
     }
-
-    Result result = dvrSp->start();
-    return (int) result;
+    sp<IDvr> iDvrSp = dvrSp->getIDvr();
+    Result result = iDvrSp->start();
+    return (jint) result;
 }
 
-static int android_media_tv_Tuner_stop_dvr(JNIEnv *env, jobject dvr) {
-    sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
+static jint android_media_tv_Tuner_stop_dvr(JNIEnv *env, jobject dvr) {
+    sp<Dvr> dvrSp = getDvr(env, dvr);
     if (dvrSp == NULL) {
         ALOGD("Failed to stop dvr: dvr not found");
-        return false;
+        return (jint) Result::NOT_INITIALIZED;
     }
-    Result result = dvrSp->stop();
-    return (int) result;
+    sp<IDvr> iDvrSp = dvrSp->getIDvr();
+    Result result = iDvrSp->stop();
+    return (jint) result;
 }
 
-static int android_media_tv_Tuner_flush_dvr(JNIEnv *env, jobject dvr) {
-    sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
+static jint android_media_tv_Tuner_flush_dvr(JNIEnv *env, jobject dvr) {
+    sp<Dvr> dvrSp = getDvr(env, dvr);
     if (dvrSp == NULL) {
         ALOGD("Failed to flush dvr: dvr not found");
-        return false;
+        return (jint) Result::NOT_INITIALIZED;
     }
-    Result result = dvrSp->flush();
-    return (int) result;
+    sp<IDvr> iDvrSp = dvrSp->getIDvr();
+    Result result = iDvrSp->flush();
+    return (jint) result;
 }
 
-static int android_media_tv_Tuner_close_dvr(JNIEnv*, jobject) {
-    return 0;
+static jint android_media_tv_Tuner_close_dvr(JNIEnv* env, jobject dvr) {
+    sp<Dvr> dvrSp = getDvr(env, dvr);
+    if (dvrSp == NULL) {
+        ALOGD("Failed to close dvr: dvr not found");
+        return (jint) Result::NOT_INITIALIZED;
+    }
+    return dvrSp->close();
 }
 
 static sp<Lnb> getLnb(JNIEnv *env, jobject lnb) {
@@ -2916,7 +2972,7 @@
     long available = dvrSp->mDvrMQ->availableToWrite();
     long write = std::min((long) size, available);
 
-    DvrMQ::MemTransaction tx;
+    MQ::MemTransaction tx;
     long ret = 0;
     if (dvrSp->mDvrMQ->beginWrite(write, &tx)) {
         auto first = tx.getFirstRegion();
@@ -2947,10 +3003,36 @@
 }
 
 static jlong android_media_tv_Tuner_read_dvr_from_array(
-        JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jlong /* offset */,
-        jlong /* size */) {
-    //TODO: impl
-    return 0;
+        JNIEnv* env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) {
+    sp<Dvr> dvrSp = getDvr(env, dvr);
+    if (dvrSp == NULL) {
+        ALOGW("Failed to read dvr: dvr not found");
+        return 0;
+    }
+    if (dvrSp->mDvrMQ == NULL) {
+        ALOGW("Failed to read dvr: dvr not configured");
+        return 0;
+    }
+
+    jlong available = dvrSp->mDvrMQ->availableToWrite();
+    size = std::min(size, available);
+
+    jboolean isCopy;
+    jbyte *src = env->GetByteArrayElements(buffer, &isCopy);
+    if (src == nullptr) {
+        ALOGD("Failed to GetByteArrayElements");
+        return 0;
+    }
+
+    if (dvrSp->mDvrMQ->write(reinterpret_cast<unsigned char*>(src) + offset, size)) {
+        env->ReleaseByteArrayElements(buffer, src, 0);
+        dvrSp->mDvrMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
+    } else {
+        ALOGD("Failed to write FMQ");
+        env->ReleaseByteArrayElements(buffer, src, 0);
+        return 0;
+    }
+    return size;
 }
 
 static jlong android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jlong size) {
@@ -2965,13 +3047,13 @@
         return 0;
     }
 
-    DvrMQ& dvrMq = dvrSp->getDvrMQ();
+    MQ& dvrMq = dvrSp->getDvrMQ();
 
     long available = dvrMq.availableToRead();
     long toRead = std::min((long) size, available);
 
     long ret = 0;
-    DvrMQ::MemTransaction tx;
+    MQ::MemTransaction tx;
     if (dvrMq.beginRead(toRead, &tx)) {
         auto first = tx.getFirstRegion();
         auto data = first.getAddress();
@@ -3001,10 +3083,17 @@
 }
 
 static jlong android_media_tv_Tuner_write_dvr_to_array(
-        JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jlong /* offset */,
-        jlong /* size */) {
-    //TODO: impl
-    return 0;
+        JNIEnv *env, jobject dvr, jbyteArray buffer, jlong offset, jlong size) {
+    sp<Dvr> dvrSp = getDvr(env, dvr);
+    if (dvrSp == NULL) {
+        ALOGW("Failed to write dvr: dvr not found");
+        return 0;
+    }
+    if (dvrSp->mDvrMQ == NULL) {
+        ALOGW("Failed to write dvr: dvr not configured");
+        return 0;
+    }
+    return copyData(env, dvrSp->mDvrMQ, dvrSp->mDvrMQEventFlag, buffer, offset, size);
 }
 
 static const JNINativeMethod gTunerMethods[] = {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 18aac28..7e860b9 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -62,8 +62,7 @@
 using ::android::hardware::tv::tuner::V1_0::RecordStatus;
 using ::android::hardware::tv::tuner::V1_0::Result;
 
-using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
-using DvrMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+using MQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
 
 namespace android {
 
@@ -84,6 +83,7 @@
 };
 
 struct DvrCallback : public IDvrCallback {
+    ~DvrCallback();
     virtual Return<void> onRecordStatus(RecordStatus status);
     virtual Return<void> onPlaybackStatus(PlaybackStatus status);
 
@@ -95,18 +95,19 @@
 struct Dvr : public RefBase {
     Dvr(sp<IDvr> sp, jweak obj);
     ~Dvr();
-    int close();
-    DvrMQ& getDvrMQ();
+    jint close();
+    MQ& getDvrMQ();
     sp<IDvr> getIDvr();
     sp<IDvr> mDvrSp;
     jweak mDvrObj;
-    std::unique_ptr<DvrMQ> mDvrMQ;
+    std::unique_ptr<MQ> mDvrMQ;
     EventFlag* mDvrMQEventFlag;
     std::string mFilePath;
     int mFd;
 };
 
 struct FilterCallback : public IFilterCallback {
+    ~FilterCallback();
     virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent);
     virtual Return<void> onFilterStatus(const DemuxFilterStatus status);
 
@@ -149,7 +150,7 @@
     int close();
     sp<IFilter> getIFilter();
     sp<IFilter> mFilterSp;
-    std::unique_ptr<FilterMQ> mFilterMQ;
+    std::unique_ptr<MQ> mFilterMQ;
     EventFlag* mFilterMQEventFlag;
     jweak mFilterObj;
 };