Android: Implement native function to expose scene information to java code.
diff --git a/android/src/org/linaro/glmark2/Glmark2Native.java b/android/src/org/linaro/glmark2/Glmark2Native.java
index 03a4c7d..0f2fd26 100644
--- a/android/src/org/linaro/glmark2/Glmark2Native.java
+++ b/android/src/org/linaro/glmark2/Glmark2Native.java
@@ -29,4 +29,5 @@
     public static native boolean render();
     public static native void done();
     public static native int scoreConfig(GLVisualConfig vc, GLVisualConfig target);
+    public static native SceneInfo[] getSceneInfo(AssetManager assetManager);
 }
diff --git a/android/src/org/linaro/glmark2/SceneInfo.java b/android/src/org/linaro/glmark2/SceneInfo.java
new file mode 100644
index 0000000..a353c7a
--- /dev/null
+++ b/android/src/org/linaro/glmark2/SceneInfo.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2012 Linaro Limited
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * glmark2.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis
+ */
+package org.linaro.glmark2;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import java.util.ArrayList;
+
+class SceneInfo implements Parcelable {
+    class Option {
+        String name;
+        String description;
+        String defaultValue;
+    }
+
+    public SceneInfo(String name) {
+        this.name = name;
+        this.options = new ArrayList<Option>();
+    }
+
+    public void addOption(String name, String description, String defaultValue) {
+        Option opt = new Option();
+        opt.name = name;
+        opt.description = description;
+        opt.defaultValue = defaultValue;
+        this.options.add(opt);
+    }
+
+    public String name;
+    public ArrayList<Option> options;
+
+    /* Parcelable interface */
+    public static final Parcelable.Creator<SceneInfo> CREATOR =
+        new Parcelable.Creator<SceneInfo>() {
+            public SceneInfo createFromParcel(Parcel in) {
+                return new SceneInfo(in);
+            }
+
+            public SceneInfo[] newArray(int size) {
+                return new SceneInfo[size];
+            }
+        };
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(name);
+        out.writeInt(options.size());
+        for (Option opt: options) {
+            out.writeString(opt.name);
+            out.writeString(opt.description);
+            out.writeString(opt.defaultValue);
+        }
+    }
+
+    private SceneInfo(Parcel in) {
+        name = in.readString();
+        options = new ArrayList<Option>();
+
+        int size = in.readInt();
+        for (int i = 0; i < size; i++) {
+            Option opt = new Option();
+            opt.name = in.readString();
+            opt.description = in.readString();
+            opt.defaultValue = in.readString();
+            options.add(opt);
+        }
+    }
+}
diff --git a/src/android.cpp b/src/android.cpp
index 9e94656..1e0973c 100644
--- a/src/android.cpp
+++ b/src/android.cpp
@@ -169,6 +169,77 @@
     vc.buffer = env->GetIntField(jvc, fid);
 }
 
+/** 
+ * Creates a SceneInfo Java object from a Scene.
+ * 
+ * @param env the JNIEnv
+ */
+static jobject
+scene_info_from_scene(JNIEnv *env, Scene &scene)
+{
+    jclass cls = env->FindClass("org/linaro/glmark2/SceneInfo");
+    jmethodID constructor = env->GetMethodID(cls, "<init>", "(Ljava/lang/String;)V");
+    jmethodID add_option = env->GetMethodID(cls, "addOption", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+
+    /* Create the SceneInfo object */
+    jstring name = env->NewStringUTF(scene.name().c_str());
+    jobject scene_info = env->NewObject(cls, constructor, name);
+
+    const std::map<std::string, Scene::Option> &options = scene.options();
+
+    /* Add options to the SceneInfo object */
+    for (std::map<std::string, Scene::Option>::const_iterator opt_iter = options.begin();
+         opt_iter != options.end();
+         opt_iter++)
+    {
+        const Scene::Option &opt = opt_iter->second;
+        jstring opt_name = env->NewStringUTF(opt.name.c_str());
+        jstring opt_description = env->NewStringUTF(opt.description.c_str());
+        jstring opt_default_value = env->NewStringUTF(opt.default_value.c_str());
+
+        env->CallVoidMethod(scene_info, add_option,
+                            opt_name,
+                            opt_description,
+                            opt_default_value);
+
+        env->DeleteLocalRef(opt_name);
+        env->DeleteLocalRef(opt_description);
+        env->DeleteLocalRef(opt_default_value);
+    }
+
+    return scene_info;
+}
+
+class DummyCanvas : public Canvas {
+public:
+    DummyCanvas() : Canvas(0, 0) {}
+};
+
+/** 
+ * Creates all the available scenes and adds them to the supplied vector.
+ * 
+ * @param scenes the vector to add the scenes to
+ * @param canvas the canvas to create the scenes with
+ */
+static void
+create_and_add_scenes(std::vector<Scene*>& scenes, Canvas& canvas)
+{
+    scenes.push_back(new SceneDefaultOptions(canvas));
+    scenes.push_back(new SceneBuild(canvas));
+    scenes.push_back(new SceneTexture(canvas));
+    scenes.push_back(new SceneShading(canvas));
+    scenes.push_back(new SceneConditionals(canvas));
+    scenes.push_back(new SceneFunction(canvas));
+    scenes.push_back(new SceneLoop(canvas));
+    scenes.push_back(new SceneBump(canvas));
+    scenes.push_back(new SceneEffect2D(canvas));
+    scenes.push_back(new ScenePulsar(canvas));
+    scenes.push_back(new SceneDesktop(canvas));
+    scenes.push_back(new SceneBuffer(canvas));
+    scenes.push_back(new SceneIdeas(canvas));
+    scenes.push_back(new SceneTerrain(canvas));
+}
+
 
 void
 Java_org_linaro_glmark2_native_init(JNIEnv* env, jclass clazz,
@@ -209,20 +280,17 @@
     Log::info("glmark2 %s\n", GLMARK_VERSION);
     g_canvas->print_info();
 
-    Benchmark::register_scene(*new SceneDefaultOptions(*g_canvas));
-    Benchmark::register_scene(*new SceneBuild(*g_canvas));
-    Benchmark::register_scene(*new SceneTexture(*g_canvas));
-    Benchmark::register_scene(*new SceneShading(*g_canvas));
-    Benchmark::register_scene(*new SceneConditionals(*g_canvas));
-    Benchmark::register_scene(*new SceneFunction(*g_canvas));
-    Benchmark::register_scene(*new SceneLoop(*g_canvas));
-    Benchmark::register_scene(*new SceneBump(*g_canvas));
-    Benchmark::register_scene(*new SceneEffect2D(*g_canvas));
-    Benchmark::register_scene(*new ScenePulsar(*g_canvas));
-    Benchmark::register_scene(*new SceneDesktop(*g_canvas));
-    Benchmark::register_scene(*new SceneBuffer(*g_canvas));
-    Benchmark::register_scene(*new SceneIdeas(*g_canvas));
-    Benchmark::register_scene(*new SceneTerrain(*g_canvas));
+    std::vector<Scene*> scenes;
+
+    /* Add and register scenes */
+    create_and_add_scenes(scenes, *g_canvas);
+
+    for (std::vector<Scene*>::const_iterator iter = scenes.begin();
+         iter != scenes.end();
+         iter++)
+    {
+        Benchmark::register_scene(**iter);
+    }
 
     g_benchmark_collection = new BenchmarkCollection();
     g_benchmark_collection->populate_from_options();
@@ -288,6 +356,42 @@
     return vc.match_score(target);
 }
 
+jobjectArray
+Java_org_linaro_glmark2_native_getSceneInfo(JNIEnv* env, jclass clazz,
+                                            jobject asset_manager)
+{
+    static_cast<void>(clazz);
+
+    Util::android_set_asset_manager(AAssetManager_fromJava(env, asset_manager));
+
+    std::vector<Scene*> scenes;
+    DummyCanvas canvas;
+    std::vector<jobject> si_vector;
+
+    create_and_add_scenes(scenes, canvas);
+
+    /* Create SceneInfo instances for all the scenes */
+    for (std::vector<Scene*>::const_iterator iter = scenes.begin();
+         iter != scenes.end();
+         iter++)
+    {
+        jobject si = scene_info_from_scene(env, **iter);
+        si_vector.push_back(si);
+    }
+
+    /* Create a SceneInfo[] array */
+    jclass si_cls = env->FindClass("org/linaro/glmark2/SceneInfo");
+    jobjectArray si_array = env->NewObjectArray(si_vector.size(), si_cls, 0);
+    
+    /* Populate the SceneInfo[] array */
+    for (size_t i = 0; i < si_vector.size(); i++)
+        env->SetObjectArrayElement(si_array, i, si_vector[i]);
+
+    Util::dispose_pointer_vector(scenes);
+
+    return si_array;
+}
+
 static JNINativeMethod glmark2_native_methods[] = {
     {
         "init",
@@ -313,6 +417,11 @@
         "scoreConfig",
         "(Lorg/linaro/glmark2/GLVisualConfig;Lorg/linaro/glmark2/GLVisualConfig;)I",
         reinterpret_cast<void*>(Java_org_linaro_glmark2_native_scoreConfig)
+    },
+    {
+        "getSceneInfo",
+        "(Landroid/content/res/AssetManager;)[Lorg/linaro/glmark2/SceneInfo;",
+        reinterpret_cast<void*>(Java_org_linaro_glmark2_native_getSceneInfo)
     }
 };