Add Descrambler handling

Test: make;
Change-Id: I9df9080c97a2e3bf706587a81400afdf954538fe
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 8805b7b..3d89909 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -17,6 +17,7 @@
 package android.media.tv.tuner;
 
 import android.annotation.Nullable;
+import android.media.tv.tuner.TunerConstants.DemuxPidType;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -83,6 +84,9 @@
     private native List<Integer> nativeGetLnbIds();
     private native Lnb nativeOpenLnbById(int id);
 
+    private native Descrambler nativeOpenDescrambler();
+
+
     /**
      * Frontend Callback.
      */
@@ -294,4 +298,27 @@
             mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_LNB_EVENT, eventType, 0));
         }
     }
+
+    protected class Descrambler {
+        private long mNativeContext;
+
+        private native boolean nativeAddPid(int pidType, int pid, Filter filter);
+        private native boolean nativeRemovePid(int pidType, int pid, Filter filter);
+
+        private Descrambler() {}
+
+        private boolean addPid(@DemuxPidType int pidType, int pid, Filter filter) {
+            return nativeAddPid(pidType, pid, filter);
+        }
+
+        private boolean removePid(@DemuxPidType int pidType, int pid, Filter filter) {
+            return nativeRemovePid(pidType, pid, filter);
+        }
+
+    }
+
+    private Descrambler openDescrambler() {
+        Descrambler descrambler = nativeOpenDescrambler();
+        return descrambler;
+    }
 }
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
index 411882e..01f9367d 100644
--- a/media/java/android/media/tv/tuner/TunerConstants.java
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -67,6 +67,14 @@
     public static final int DATA_FORMAT_ES = Constants.DataFormat.ES;
     public static final int DATA_FORMAT_SHV_TLV = Constants.DataFormat.SHV_TLV;
 
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({DEMUX_T_PID, DEMUX_MMPT_PID})
+    public @interface DemuxPidType {}
+
+    public static final int DEMUX_T_PID = 1;
+    public static final int DEMUX_MMPT_PID = 2;
+
     private TunerConstants() {
     }
 }
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 35607ac..efdd333 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -28,19 +28,23 @@
 using ::android::hardware::Void;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxMmtpPid;
+using ::android::hardware::tv::tuner::V1_0::DemuxTpid;
 using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
 using ::android::hardware::tv::tuner::V1_0::ITuner;
 using ::android::hardware::tv::tuner::V1_0::Result;
 
 struct fields_t {
-    jfieldID context;
+    jfieldID tunerContext;
     jfieldID filterContext;
+    jfieldID descramblerContext;
     jmethodID frontendInitID;
     jmethodID filterInitID;
     jmethodID onFrontendEventID;
     jmethodID onFilterStatusID;
     jmethodID lnbInitID;
     jmethodID onLnbEventID;
+    jmethodID descramblerInitID;
 };
 
 static fields_t gFields;
@@ -258,6 +262,33 @@
     return true;
 }
 
+jobject JTuner::openDescrambler() {
+    ALOGD("JTuner::openDescrambler");
+    if (mTuner == nullptr) {
+        return NULL;
+    }
+    sp<IDescrambler> descramblerSp;
+    mTuner->openDescrambler([&](Result, const sp<IDescrambler>& descrambler) {
+        descramblerSp = descrambler;
+    });
+
+    if (descramblerSp == NULL) {
+        return NULL;
+    }
+
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    jobject descramblerObj =
+            env->NewObject(
+                    env->FindClass("android/media/tv/tuner/Tuner$Descrambler"),
+                    gFields.descramblerInitID,
+                    mObject);
+
+    descramblerSp->incStrong(descramblerObj);
+    env->SetLongField(descramblerObj, gFields.descramblerContext, (jlong)descramblerSp.get());
+
+    return descramblerObj;
+}
+
 jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
     if (mDemux == NULL) {
         if (!openDemux()) {
@@ -303,7 +334,7 @@
 using namespace android;
 
 static sp<JTuner> setTuner(JNIEnv *env, jobject thiz, const sp<JTuner> &tuner) {
-    sp<JTuner> old = (JTuner *)env->GetLongField(thiz, gFields.context);
+    sp<JTuner> old = (JTuner *)env->GetLongField(thiz, gFields.tunerContext);
 
     if (tuner != NULL) {
         tuner->incStrong(thiz);
@@ -311,13 +342,27 @@
     if (old != NULL) {
         old->decStrong(thiz);
     }
-    env->SetLongField(thiz, gFields.context, (jlong)tuner.get());
+    env->SetLongField(thiz, gFields.tunerContext, (jlong)tuner.get());
 
     return old;
 }
 
 static sp<JTuner> getTuner(JNIEnv *env, jobject thiz) {
-    return (JTuner *)env->GetLongField(thiz, gFields.context);
+    return (JTuner *)env->GetLongField(thiz, gFields.tunerContext);
+}
+
+static sp<IDescrambler> getDescrambler(JNIEnv *env, jobject descrambler) {
+    return (IDescrambler *)env->GetLongField(descrambler, gFields.descramblerContext);
+}
+
+static DemuxPid getDemuxPid(int pidType, int pid) {
+    DemuxPid demuxPid;
+    if ((int)pidType == 1) {
+        demuxPid.tPid(static_cast<DemuxTpid>(pid));
+    } else if ((int)pidType == 2) {
+        demuxPid.mmtpPid(static_cast<DemuxMmtpPid>(pid));
+    }
+    return demuxPid;
 }
 
 static sp<IFilter> getFilter(JNIEnv *env, jobject filter) {
@@ -328,8 +373,8 @@
     jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
     CHECK(clazz != NULL);
 
-    gFields.context = env->GetFieldID(clazz, "mNativeContext", "J");
-    CHECK(gFields.context != NULL);
+    gFields.tunerContext = env->GetFieldID(clazz, "mNativeContext", "J");
+    CHECK(gFields.tunerContext != NULL);
 
     gFields.onFrontendEventID = env->GetMethodID(clazz, "onFrontendEvent", "(I)V");
 
@@ -349,6 +394,11 @@
             env->GetMethodID(filterClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
     gFields.onFilterStatusID =
             env->GetMethodID(filterClazz, "onFilterStatus", "(I)V");
+
+    jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Tuner$Descrambler");
+    gFields.descramblerContext = env->GetFieldID(descramblerClazz, "mNativeContext", "J");
+    gFields.descramblerInitID =
+            env->GetMethodID(descramblerClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;)V");
 }
 
 static void android_media_tv_Tuner_native_setup(JNIEnv *env, jobject thiz) {
@@ -416,6 +466,33 @@
     return filterSp->flush() == Result::SUCCESS;
 }
 
+static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz) {
+    sp<JTuner> tuner = getTuner(env, thiz);
+    return tuner->openDescrambler();
+}
+
+static bool android_media_tv_Tuner_add_pid(
+        JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
+    sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
+    if (descramblerSp == NULL) {
+        return false;
+    }
+    sp<IFilter> filterSp = getFilter(env, filter);
+    Result result = descramblerSp->addPid(getDemuxPid((int)pidType, (int)pid), filterSp);
+    return result == Result::SUCCESS;
+}
+
+static bool android_media_tv_Tuner_remove_pid(
+        JNIEnv *env, jobject descrambler, jint pidType, jint pid, jobject filter) {
+    sp<IDescrambler> descramblerSp = getDescrambler(env, descrambler);
+    if (descramblerSp == NULL) {
+        return false;
+    }
+    sp<IFilter> filterSp = getFilter(env, filter);
+    Result result = descramblerSp->removePid(getDemuxPid((int)pidType, (int)pid), filterSp);
+    return result == Result::SUCCESS;
+}
+
 static const JNINativeMethod gTunerMethods[] = {
     { "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init },
     { "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup },
@@ -429,6 +506,8 @@
             (void *)android_media_tv_Tuner_get_lnb_ids },
     { "nativeOpenLnbById", "(I)Landroid/media/tv/tuner/Tuner$Lnb;",
             (void *)android_media_tv_Tuner_open_lnb_by_id },
+    { "nativeOpenDescrambler", "()Landroid/media/tv/tuner/Tuner$Descrambler;",
+            (void *)android_media_tv_Tuner_open_descrambler },
 };
 
 static const JNINativeMethod gFilterMethods[] = {
@@ -437,6 +516,13 @@
     { "nativeFlushFilter", "()Z", (void *)android_media_tv_Tuner_flush_filter },
 };
 
+static const JNINativeMethod gDescramblerMethods[] = {
+    { "nativeAddPid", "(IILandroid/media/tv/tuner/Tuner$Filter;)Z",
+            (void *)android_media_tv_Tuner_add_pid },
+    { "nativeRemovePid", "(IILandroid/media/tv/tuner/Tuner$Filter;)Z",
+            (void *)android_media_tv_Tuner_remove_pid },
+};
+
 static bool register_android_media_tv_Tuner(JNIEnv *env) {
     if (AndroidRuntime::registerNativeMethods(
             env, "android/media/tv/tuner/Tuner", gTunerMethods, NELEM(gTunerMethods)) != JNI_OK) {
@@ -450,6 +536,13 @@
         ALOGE("Failed to register filter native methods");
         return false;
     }
+    if (AndroidRuntime::registerNativeMethods(
+            env, "android/media/tv/tuner/Tuner$Descrambler",
+            gDescramblerMethods,
+            NELEM(gDescramblerMethods)) != JNI_OK) {
+        ALOGE("Failed to register descrambler native methods");
+        return false;
+    }
     return true;
 }
 
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index f42f032..d3aec64 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -28,11 +28,13 @@
 using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
 using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
 using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxPid;
 using ::android::hardware::tv::tuner::V1_0::FrontendEventType;
 using ::android::hardware::tv::tuner::V1_0::FrontendId;
 using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
 using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
 using ::android::hardware::tv::tuner::V1_0::IDemux;
+using ::android::hardware::tv::tuner::V1_0::IDescrambler;
 using ::android::hardware::tv::tuner::V1_0::IFilter;
 using ::android::hardware::tv::tuner::V1_0::IFilterCallback;
 using ::android::hardware::tv::tuner::V1_0::IFrontend;
@@ -82,6 +84,7 @@
     jobject getLnbIds();
     jobject openLnbById(int id);
     jobject openFilter(DemuxFilterType type, int bufferSize);
+    jobject openDescrambler();
 
 protected:
     bool openDemux();