Add DvrSettings

Test: make; cuttlefish;
Change-Id: Ia7e3199a4aa794dc41bf5d10f09fbf82b41b512f
diff --git a/media/java/android/media/tv/tuner/DvrSettings.java b/media/java/android/media/tv/tuner/DvrSettings.java
new file mode 100644
index 0000000..76160dc
--- /dev/null
+++ b/media/java/android/media/tv/tuner/DvrSettings.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2019 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 android.media.tv.tuner;
+
+import android.media.tv.tuner.TunerConstants.DataFormat;
+import android.media.tv.tuner.TunerConstants.DvrSettingsType;
+
+/**
+ * DVR settings.
+ *
+ * @hide
+ */
+public class DvrSettings {
+    private int mStatusMask;
+    private int mLowThreshold;
+    private int mHighThreshold;
+    private int mPacketSize;
+
+    @DataFormat
+    private int mDataFormat;
+    @DvrSettingsType
+    private int mType;
+
+    private DvrSettings(int statusMask, int lowThreshold, int highThreshold, int packetSize,
+            @DataFormat int dataFormat, @DvrSettingsType int type) {
+        mStatusMask = statusMask;
+        mLowThreshold = lowThreshold;
+        mHighThreshold = highThreshold;
+        mPacketSize = packetSize;
+        mDataFormat = dataFormat;
+        mType = type;
+    }
+
+    /**
+     * Creates a new builder.
+     */
+    public static Builder newBuilder() {
+        return new Builder();
+    }
+
+    /**
+     * Builder for DvrSettings.
+     */
+    public static final class Builder {
+        private int mStatusMask;
+        private int mLowThreshold;
+        private int mHighThreshold;
+        private int mPacketSize;
+        @DataFormat
+        private int mDataFormat;
+        @DvrSettingsType
+        private int mType;
+
+        /**
+         * Sets status mask.
+         */
+        public Builder setStatusMask(int statusMask) {
+            this.mStatusMask = statusMask;
+            return this;
+        }
+
+        /**
+         * Sets low threshold.
+         */
+        public Builder setLowThreshold(int lowThreshold) {
+            this.mLowThreshold = lowThreshold;
+            return this;
+        }
+
+        /**
+         * Sets high threshold.
+         */
+        public Builder setHighThreshold(int highThreshold) {
+            this.mHighThreshold = highThreshold;
+            return this;
+        }
+
+        /**
+         * Sets packet size.
+         */
+        public Builder setPacketSize(int packetSize) {
+            this.mPacketSize = packetSize;
+            return this;
+        }
+
+        /**
+         * Sets data format.
+         */
+        public Builder setDataFormat(@DataFormat int dataFormat) {
+            this.mDataFormat = dataFormat;
+            return this;
+        }
+
+        /**
+         * Sets settings type.
+         */
+        public Builder setType(@DvrSettingsType int type) {
+            this.mType = type;
+            return this;
+        }
+
+        /**
+         * Builds a DvrSettings instance.
+         */
+        public DvrSettings build() {
+            return new DvrSettings(
+                    mStatusMask, mLowThreshold, mHighThreshold, mPacketSize, mDataFormat, mType);
+        }
+    }
+}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 6537f6f..4c93101 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -368,6 +368,7 @@
 
         private native boolean nativeAttachFilter(Filter filter);
         private native boolean nativeDetachFilter(Filter filter);
+        private native int nativeConfigureDvr(DvrSettings settings);
         private native boolean nativeStartDvr();
         private native boolean nativeStopDvr();
         private native boolean nativeFlushDvr();
@@ -380,6 +381,9 @@
         public boolean detachFilter(Filter filter) {
             return nativeDetachFilter(filter);
         }
+        public int configure(DvrSettings settings) {
+            return nativeConfigureDvr(settings);
+        }
         public boolean start() {
             return nativeStartDvr();
         }
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
index f2d5e93..261b2de 100644
--- a/media/java/android/media/tv/tuner/TunerConstants.java
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -101,6 +101,13 @@
     public static final int FILTER_SETTINGS_TLV = Constants.DemuxFilterMainType.TLV;
     public static final int FILTER_SETTINGS_ALP = Constants.DemuxFilterMainType.ALP;
 
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({DVR_SETTINGS_RECORD, DVR_SETTINGS_PLAYBACK})
+    public @interface DvrSettingsType {}
+
+    public static final int DVR_SETTINGS_RECORD = Constants.DvrType.RECORD;
+    public static final int DVR_SETTINGS_PLAYBACK = Constants.DvrType.PLAYBACK;
+
     private TunerConstants() {
     }
 }
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index a0be12e..5fa6a1f 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -27,6 +27,7 @@
 
 using ::android::hardware::Void;
 using ::android::hardware::hidl_vec;
+using ::android::hardware::tv::tuner::V1_0::DataFormat;
 using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
 using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
 using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
@@ -35,10 +36,13 @@
 using ::android::hardware::tv::tuner::V1_0::DemuxTpid;
 using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
 using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using ::android::hardware::tv::tuner::V1_0::DvrSettings;
 using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSettings;
 using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard;
 using ::android::hardware::tv::tuner::V1_0::FrontendAnalogType;
 using ::android::hardware::tv::tuner::V1_0::ITuner;
+using ::android::hardware::tv::tuner::V1_0::PlaybackSettings;
+using ::android::hardware::tv::tuner::V1_0::RecordSettings;
 using ::android::hardware::tv::tuner::V1_0::Result;
 
 struct fields_t {
@@ -485,6 +489,49 @@
     return (Filter *)env->GetLongField(filter, gFields.filterContext);
 }
 
+static DvrSettings getDvrSettings(JNIEnv *env, jobject settings) {
+    DvrSettings dvrSettings;
+    jclass clazz = env->FindClass("android/media/tv/tuner/DvrSettings");
+    uint32_t statusMask =
+            static_cast<uint32_t>(env->GetIntField(
+                    settings, env->GetFieldID(clazz, "mStatusMask", "I")));
+    uint32_t lowThreshold =
+            static_cast<uint32_t>(env->GetIntField(
+                    settings, env->GetFieldID(clazz, "mLowThreshold", "I")));
+    uint32_t highThreshold =
+            static_cast<uint32_t>(env->GetIntField(
+                    settings, env->GetFieldID(clazz, "mHighThreshold", "I")));
+    uint8_t packetSize =
+            static_cast<uint8_t>(env->GetIntField(
+                    settings, env->GetFieldID(clazz, "mPacketSize", "I")));
+    DataFormat dataFormat =
+            static_cast<DataFormat>(env->GetIntField(
+                    settings, env->GetFieldID(clazz, "mDataFormat", "I")));
+    DvrType type =
+            static_cast<DvrType>(env->GetIntField(
+                    settings, env->GetFieldID(clazz, "mType", "I")));
+    if (type == DvrType::RECORD) {
+        RecordSettings recordSettings {
+                .statusMask = static_cast<unsigned char>(statusMask),
+                .lowThreshold = lowThreshold,
+                .highThreshold = highThreshold,
+                .dataFormat = dataFormat,
+                .packetSize = packetSize,
+        };
+        dvrSettings.record(recordSettings);
+    } else if (type == DvrType::PLAYBACK) {
+        PlaybackSettings PlaybackSettings {
+                .statusMask = statusMask,
+                .lowThreshold = lowThreshold,
+                .highThreshold = highThreshold,
+                .dataFormat = dataFormat,
+                .packetSize = packetSize,
+        };
+        dvrSettings.playback(PlaybackSettings);
+    }
+    return dvrSettings;
+}
+
 static sp<IDvr> getDvr(JNIEnv *env, jobject dvr) {
     return (IDvr *)env->GetLongField(dvr, gFields.dvrContext);
 }
@@ -749,6 +796,16 @@
     return result == Result::SUCCESS;
 }
 
+static int android_media_tv_Tuner_configure_dvr(JNIEnv *env, jobject dvr, jobject settings) {
+    sp<IDvr> dvrSp = getDvr(env, dvr);
+    if (dvrSp == NULL) {
+        ALOGD("Failed to configure dvr: dvr not found");
+        return (int)Result::INVALID_STATE;
+    }
+    Result result = dvrSp->configure(getDvrSettings(env, settings));
+    return (int)result;
+}
+
 static bool android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) {
     sp<IDvr> dvrSp = getDvr(env, dvr);
     if (dvrSp == NULL) {
@@ -818,6 +875,8 @@
             (void *)android_media_tv_Tuner_attach_filter },
     { "nativeDetachFilter", "(Landroid/media/tv/tuner/Tuner$Filter;)Z",
             (void *)android_media_tv_Tuner_detach_filter },
+    { "nativeConfigureDvr", "(Landroid/media/tv/tuner/DvrSettings;)I",
+            (void *)android_media_tv_Tuner_configure_dvr },
     { "nativeStartDvr", "()Z", (void *)android_media_tv_Tuner_start_dvr },
     { "nativeStopDvr", "()Z", (void *)android_media_tv_Tuner_stop_dvr },
     { "nativeFlushDvr", "()Z", (void *)android_media_tv_Tuner_flush_dvr },