media: add SyncSettings to MediaSync and MediaPlayer

Bug: 18249558
Change-Id: I76d7e20d0e0c2d1d24bf60ade6386986573476f0
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index c8464c7..dbb53b4 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -2,6 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
+    android_media_AmrInputStream.cpp \
     android_media_ImageWriter.cpp \
     android_media_ImageReader.cpp \
     android_media_MediaCrypto.cpp \
@@ -14,12 +15,12 @@
     android_media_MediaMetadataRetriever.cpp \
     android_media_MediaMuxer.cpp \
     android_media_MediaPlayer.cpp \
+    android_media_MediaProfiles.cpp \
     android_media_MediaRecorder.cpp \
     android_media_MediaScanner.cpp \
     android_media_MediaSync.cpp \
     android_media_ResampleInputStream.cpp \
-    android_media_MediaProfiles.cpp \
-    android_media_AmrInputStream.cpp \
+    android_media_SyncSettings.cpp \
     android_media_Utils.cpp \
     android_mtp_MtpDatabase.cpp \
     android_mtp_MtpDevice.cpp \
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index b79a6bb..2c61779 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -39,6 +39,7 @@
 #include "utils/String8.h"
 #include "android_media_MediaDataSource.h"
 #include "android_media_PlaybackSettings.h"
+#include "android_media_SyncSettings.h"
 #include "android_media_Utils.h"
 
 #include "android_os_Parcel.h"
@@ -69,6 +70,7 @@
 static fields_t fields;
 
 static PlaybackSettings::fields_t gPlaybackSettingsFields;
+static SyncSettings::fields_t gSyncSettingsFields;
 
 static Mutex sLock;
 
@@ -476,6 +478,56 @@
 }
 
 static void
+android_media_MediaPlayer_setSyncSettings(JNIEnv *env, jobject thiz, jobject settings)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    SyncSettings scs;
+    scs.fillFromJobject(env, gSyncSettingsFields, settings);
+    ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f",
+            scs.syncSourceSet, scs.syncSource,
+            scs.audioAdjustModeSet, scs.audioAdjustMode,
+            scs.toleranceSet, scs.tolerance,
+            scs.frameRateSet, scs.frameRate);
+
+    // TODO: pass sync settings to mediaplayer when it supports it
+    // process_media_player_call(env, thiz, mp->setSyncSettings(scs), NULL, NULL);
+}
+
+static jobject
+android_media_MediaPlayer_getSyncSettings(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return NULL;
+    }
+
+    SyncSettings scs;
+    scs.syncSource = 0; // SYNC_SOURCE_DEFAULT
+    scs.audioAdjustMode = 0; // AUDIO_ADJUST_MODE_DEFAULT
+    scs.tolerance = 0.f;
+    scs.frameRate = 0.f;
+
+    // TODO: get this from mediaplayer when it supports it
+    // process_media_player_call(
+    //        env, thiz, mp->getSyncSettings(&scs), NULL, NULL);
+    ALOGV("getSyncSettings: %d %d %f %f",
+            scs.syncSource, scs.audioAdjustMode, scs.tolerance, scs.frameRate);
+
+    scs.syncSourceSet = true;
+    scs.audioAdjustModeSet = true;
+    scs.toleranceSet = true;
+    scs.frameRateSet = false;
+
+    return scs.asJobject(env, gSyncSettingsFields);
+}
+
+static void
 android_media_MediaPlayer_seekTo(JNIEnv *env, jobject thiz, jint msec)
 {
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
@@ -760,6 +812,7 @@
     env->DeleteLocalRef(clazz);
 
     gPlaybackSettingsFields.init(env);
+    gSyncSettingsFields.init(env);
 }
 
 static void
@@ -950,6 +1003,8 @@
     {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer_getVideoHeight},
     {"setPlaybackSettings", "(Landroid/media/PlaybackSettings;)V", (void *)android_media_MediaPlayer_setPlaybackSettings},
     {"getPlaybackSettings", "()Landroid/media/PlaybackSettings;", (void *)android_media_MediaPlayer_getPlaybackSettings},
+    {"setSyncSettings",     "(Landroid/media/SyncSettings;)V",  (void *)android_media_MediaPlayer_setSyncSettings},
+    {"getSyncSettings",     "()Landroid/media/SyncSettings;",   (void *)android_media_MediaPlayer_getSyncSettings},
     {"seekTo",              "(I)V",                             (void *)android_media_MediaPlayer_seekTo},
     {"_pause",              "()V",                              (void *)android_media_MediaPlayer_pause},
     {"isPlaying",           "()Z",                              (void *)android_media_MediaPlayer_isPlaying},
diff --git a/media/jni/android_media_MediaSync.cpp b/media/jni/android_media_MediaSync.cpp
index e167f83..72dacdf 100644
--- a/media/jni/android_media_MediaSync.cpp
+++ b/media/jni/android_media_MediaSync.cpp
@@ -21,6 +21,7 @@
 #include "android_media_MediaSync.h"
 
 #include "android_media_AudioTrack.h"
+#include "android_media_SyncSettings.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/android_view_Surface.h"
 #include "jni.h"
@@ -46,6 +47,7 @@
 };
 
 static fields_t gFields;
+static SyncSettings::fields_t gSyncSettingsFields;
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -266,6 +268,55 @@
     return JNI_TRUE;
 }
 
+static void
+android_media_MediaSync_setSyncSettings(JNIEnv *env, jobject thiz, jobject settings)
+{
+    sp<JMediaSync> sync = getMediaSync(env, thiz);
+    if (sync == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return;
+    }
+
+    SyncSettings scs;
+    scs.fillFromJobject(env, gSyncSettingsFields, settings);
+    ALOGV("setSyncSettings: %d:%d %d:%d %d:%f %d:%f",
+            scs.syncSourceSet, scs.syncSource,
+            scs.audioAdjustModeSet, scs.audioAdjustMode,
+            scs.toleranceSet, scs.tolerance,
+            scs.frameRateSet, scs.frameRate);
+
+    // TODO: pass sync settings to mediasync when it supports it
+}
+
+static jobject
+android_media_MediaSync_getSyncSettings(JNIEnv *env, jobject thiz)
+{
+    sp<JMediaSync> sync = getMediaSync(env, thiz);
+    if (sync == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return NULL;
+    }
+
+    SyncSettings scs;
+    scs.syncSource = 0; // SYNC_SOURCE_DEFAULT
+    scs.audioAdjustMode = 0; // AUDIO_ADJUST_MODE_DEFAULT
+    scs.tolerance = 0.f;
+    scs.frameRate = 0.f;
+
+    // TODO: get this from mediaplayer when it supports it
+    // process_media_player_call(
+    //        env, thiz, mp->getSyncSettings(&scs), NULL, NULL);
+    ALOGV("getSyncSettings: %d %d %f %f",
+            scs.syncSource, scs.audioAdjustMode, scs.tolerance, scs.frameRate);
+
+    scs.syncSourceSet = true;
+    scs.audioAdjustModeSet = true;
+    scs.toleranceSet = true;
+    scs.frameRateSet = false;
+
+    return scs.asJobject(env, gSyncSettingsFields);
+}
+
 static void android_media_MediaSync_native_init(JNIEnv *env) {
     ScopedLocalRef<jclass> clazz(env, env->FindClass("android/media/MediaSync"));
     CHECK(clazz.get() != NULL);
@@ -287,6 +338,8 @@
     gFields.mediaTimestampClockRateID =
         env->GetFieldID(clazz.get(), "clockRate", "F");
     CHECK(gFields.mediaTimestampClockRateID != NULL);
+
+    gSyncSettingsFields.init(env);
 }
 
 static void android_media_MediaSync_native_setup(JNIEnv *env, jobject thiz) {
@@ -342,6 +395,10 @@
 
     { "native_setPlaybackRate", "(F)V", (void *)android_media_MediaSync_native_setPlaybackRate },
 
+    { "setSyncSettings", "(Landroid/media/SyncSettings;)V", (void *)android_media_MediaSync_setSyncSettings},
+
+    { "getSyncSettings", "()Landroid/media/SyncSettings;", (void *)android_media_MediaSync_getSyncSettings},
+
     { "native_finalize", "()V", (void *)android_media_MediaSync_native_finalize },
 };
 
diff --git a/media/jni/android_media_SyncSettings.cpp b/media/jni/android_media_SyncSettings.cpp
new file mode 100644
index 0000000..2f0605e
--- /dev/null
+++ b/media/jni/android_media_SyncSettings.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2015, 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.
+ */
+
+#include "android_media_SyncSettings.h"
+
+#include "JNIHelp.h"
+
+namespace android {
+
+void SyncSettings::fields_t::init(JNIEnv *env) {
+    jclass lclazz = env->FindClass("android/media/SyncSettings");
+    if (lclazz == NULL) {
+        return;
+    }
+
+    clazz = (jclass)env->NewGlobalRef(lclazz);
+    if (clazz == NULL) {
+        return;
+    }
+
+    constructID = env->GetMethodID(clazz, "<init>", "()V");
+
+    sync_source = env->GetFieldID(clazz, "mSyncSource", "I");
+    audio_adjust_mode = env->GetFieldID(clazz, "mAudioAdjustMode", "I");
+    tolerance = env->GetFieldID(clazz, "mTolerance", "F");
+    frame_rate = env->GetFieldID(clazz, "mFrameRate", "F");
+    set = env->GetFieldID(clazz, "mSet", "I");
+
+    set_sync_source =
+        env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "SET_SYNC_SOURCE", "I"));
+    set_audio_adjust_mode = env->GetStaticIntField(
+            clazz, env->GetStaticFieldID(clazz, "SET_AUDIO_ADJUST_MODE", "I"));
+    set_tolerance =
+        env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "SET_TOLERANCE", "I"));
+    set_frame_rate =
+        env->GetStaticIntField(clazz, env->GetStaticFieldID(clazz, "SET_FRAME_RATE", "I"));
+
+    env->DeleteLocalRef(lclazz);
+}
+
+void SyncSettings::fields_t::exit(JNIEnv *env) {
+    env->DeleteGlobalRef(clazz);
+    clazz = NULL;
+}
+
+void SyncSettings::fillFromJobject(JNIEnv *env, const fields_t& fields, jobject settings) {
+    syncSource = env->GetIntField(settings, fields.sync_source);
+    audioAdjustMode = env->GetIntField(settings, fields.audio_adjust_mode);
+    tolerance = env->GetFloatField(settings, fields.tolerance);
+    frameRate = env->GetFloatField(settings, fields.frame_rate);
+    int set = env->GetIntField(settings, fields.set);
+
+    syncSourceSet = set & fields.set_sync_source;
+    audioAdjustModeSet = set & fields.set_audio_adjust_mode;
+    toleranceSet = set & fields.set_tolerance;
+    frameRateSet = set & fields.set_frame_rate;
+}
+
+jobject SyncSettings::asJobject(JNIEnv *env, const fields_t& fields) {
+    jobject settings = env->NewObject(fields.clazz, fields.constructID);
+    if (settings == NULL) {
+        return NULL;
+    }
+    env->SetIntField(settings, fields.sync_source, (jint)syncSource);
+    env->SetIntField(settings, fields.audio_adjust_mode, (jint)audioAdjustMode);
+    env->SetFloatField(settings, fields.tolerance, (jfloat)tolerance);
+    env->SetFloatField(settings, fields.frame_rate, (jfloat)frameRate);
+    env->SetIntField(
+            settings, fields.set,
+            (syncSourceSet ? fields.set_sync_source : 0)
+                    | (audioAdjustModeSet ? fields.set_audio_adjust_mode : 0)
+                    | (toleranceSet ? fields.set_tolerance : 0)
+                    | (frameRateSet ? fields.set_frame_rate : 0));
+
+    return settings;
+}
+
+}  // namespace android
diff --git a/media/jni/android_media_SyncSettings.h b/media/jni/android_media_SyncSettings.h
new file mode 100644
index 0000000..586533f
--- /dev/null
+++ b/media/jni/android_media_SyncSettings.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015, 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.
+ */
+
+#ifndef _ANDROID_MEDIA_SYNC_SETTINGS_H_
+#define _ANDROID_MEDIA_SYNC_SETTINGS_H_
+
+#include "jni.h"
+
+namespace android {
+
+struct SyncSettings {
+    // keep this here until it is implemented
+    int syncSource;
+    int audioAdjustMode;
+    float tolerance;
+    float frameRate;
+
+    bool syncSourceSet;
+    bool audioAdjustModeSet;
+    bool toleranceSet;
+    bool frameRateSet;
+
+    struct fields_t {
+        jclass      clazz;
+        jmethodID   constructID;
+
+        jfieldID    sync_source;
+        jfieldID    audio_adjust_mode;
+        jfieldID    tolerance;
+        jfieldID    frame_rate;
+        jfieldID    set;
+        jint        set_sync_source;
+        jint        set_audio_adjust_mode;
+        jint        set_tolerance;
+        jint        set_frame_rate;
+
+        // initializes fields
+        void init(JNIEnv *env);
+
+        // releases global references held
+        void exit(JNIEnv *env);
+    };
+
+    // fills this from an android.media.SyncSettings object
+    void fillFromJobject(JNIEnv *env, const fields_t& fields, jobject settings);
+
+    // returns this as a android.media.SyncSettings object
+    jobject asJobject(JNIEnv *env, const fields_t& fields);
+};
+
+}  // namespace android
+
+#endif  // _ANDROID_MEDIA_SYNC_SETTINGS_H_