demos: Enable validation for Android cube
authorCody Northrop <cnorthrop@google.com>
Tue, 27 Sep 2016 03:05:00 +0000 (21:05 -0600)
committerCody Northrop <cnorthrop@google.com>
Wed, 28 Sep 2016 16:36:18 +0000 (10:36 -0600)
common/android_util.cpp [new file with mode: 0644]
common/android_util.h [new file with mode: 0644]
demos/android/jni/Android.mk
demos/cube.c

diff --git a/common/android_util.cpp b/common/android_util.cpp
new file mode 100644 (file)
index 0000000..c2c4616
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2016 Google, Inc.
+ *
+ * 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.
+ *
+ * Relicensed from the WTFPL (http://www.wtfpl.net/faq/).
+ */
+
+#include "android_util.h"
+#include <android_native_app_glue.h>
+#include <cassert>
+#include <vector>
+#include <string>
+#include <sstream>
+
+extern "C" {
+
+// Convert Intents to arg list, returning argc and argv
+// Note that this C routine mallocs memory that the caller must free
+char** get_args(struct android_app* app, const char* intent_extra_data_key, const char* appTag, int* count)
+{
+    std::vector<std::string> args;
+    JavaVM &vm = *app->activity->vm;
+    JNIEnv *p_env;
+    if (vm.AttachCurrentThread(&p_env, nullptr) != JNI_OK)
+        return nullptr;
+
+    JNIEnv &env = *p_env;
+    jobject activity = app->activity->clazz;
+    jmethodID get_intent_method = env.GetMethodID(env.GetObjectClass(activity),
+            "getIntent", "()Landroid/content/Intent;");
+    jobject intent = env.CallObjectMethod(activity, get_intent_method);
+    jmethodID get_string_extra_method = env.GetMethodID(env.GetObjectClass(intent),
+            "getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;");
+    jvalue get_string_extra_args;
+    get_string_extra_args.l = env.NewStringUTF(intent_extra_data_key);
+    jstring extra_str = static_cast<jstring>(env.CallObjectMethodA(intent,
+            get_string_extra_method, &get_string_extra_args));
+
+    std::string args_str;
+    if (extra_str) {
+        const char *extra_utf = env.GetStringUTFChars(extra_str, nullptr);
+        args_str = extra_utf;
+        env.ReleaseStringUTFChars(extra_str, extra_utf);
+        env.DeleteLocalRef(extra_str);
+    }
+
+    env.DeleteLocalRef(get_string_extra_args.l);
+    env.DeleteLocalRef(intent);
+    vm.DetachCurrentThread();
+
+    // split args_str
+    std::stringstream ss(args_str);
+    std::string arg;
+    while (std::getline(ss, arg, ' ')) {
+        if (!arg.empty())
+            args.push_back(arg);
+    }
+
+    // Convert our STL results to C friendly constructs
+    assert(count != nullptr);
+    *count = args.size() + 1;
+    char** vector = (char**) malloc(*count * sizeof(char*));
+    const char* appName = appTag ? appTag : (const char*) "appTag";
+
+   vector[0] = (char*) malloc(strlen(appName) * sizeof(char));
+   strcpy(vector[0], appName);
+
+    for (uint32_t i = 0; i < args.size(); i++) {
+        vector[i + 1] = (char*) malloc(strlen(args[i].c_str()) * sizeof(char));
+        strcpy(vector[i + 1], args[i].c_str());
+    }
+
+    return vector;
+}
+
+} // extern "C"
diff --git a/common/android_util.h b/common/android_util.h
new file mode 100644 (file)
index 0000000..666afff
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016 Google, Inc.
+ *
+ * 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.
+ *
+ * Relicensed from the WTFPL (http://www.wtfpl.net/faq/).
+ */
+
+#ifndef ANDROID_UTIL_H
+#define ANDROID_UTIL_H
+
+#ifdef __cplusplus
+    extern "C" {
+#endif
+
+char** get_args(struct android_app* app, const char* intent_extra_data_key, const char* appTag, int* count);
+
+#ifdef __cplusplus
+    }
+#endif
+
+#endif
index 5042102..51cf0ba 100644 (file)
@@ -33,7 +33,8 @@ include $(BUILD_SHARED_LIBRARY)
 include $(CLEAR_VARS)
 LOCAL_MODULE := Cube
 LOCAL_SRC_FILES += $(DEMO_DIR)/cube.c \
-                   $(SRC_DIR)/common/vulkan_wrapper.cpp
+                   $(SRC_DIR)/common/vulkan_wrapper.cpp \
+                   $(SRC_DIR)/common/android_util.cpp
 LOCAL_C_INCLUDES += $(SRC_DIR)/include \
                     $(DEMO_DIR)/android/include \
                     $(SRC_DIR)/libs \
index 381df5f..42a6f73 100644 (file)
@@ -451,6 +451,20 @@ dbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
     if (!demo->suppress_popups)
         MessageBox(NULL, message, "Alert", MB_OK);
     in_callback = false;
+#elif defined(ANDROID)
+    if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
+        __android_log_print(ANDROID_LOG_INFO,  "Cube", "%s", message);
+    } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
+        __android_log_print(ANDROID_LOG_WARN,  "Cube", "%s", message);
+    } else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
+        __android_log_print(ANDROID_LOG_WARN,  "Cube", "%s", message);
+    } else if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
+        __android_log_print(ANDROID_LOG_ERROR, "Cube", "%s", message);
+    } else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
+        __android_log_print(ANDROID_LOG_DEBUG, "Cube", "%s", message);
+    } else {
+        __android_log_print(ANDROID_LOG_INFO,  "Cube", "%s", message);
+    }
 #else
     printf("%s\n", message);
     fflush(stdout);
@@ -3309,6 +3323,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine,
 #elif defined(VK_USE_PLATFORM_ANDROID_KHR)
 #include <android/log.h>
 #include <android_native_app_glue.h>
+#include "android_util.h"
+
 static bool initialized = false;
 static bool active = false;
 struct demo demo;
@@ -3334,7 +3350,25 @@ static void processCommand(struct android_app* app, int32_t cmd) {
                 if (demo.prepared) {
                     demo_cleanup(&demo);
                 }
-                demo_init(&demo, 0, NULL);
+
+                // Parse Intents into argc, argv
+                // Use the following key to send arguments, i.e.
+                // --es args "--validate"
+                const char key[] = "args";
+                char* appTag = (char*) "Cube";
+                int argc = 0;
+                char** argv = get_args(app, key, appTag, &argc);
+
+                __android_log_print(ANDROID_LOG_INFO, appTag, "argc = %i", argc);
+                for (int i = 0; i < argc; i++)
+                    __android_log_print(ANDROID_LOG_INFO, appTag, "argv[%i] = %s", i, argv[i]);
+
+                demo_init(&demo, argc, argv);
+
+                // Free the argv malloc'd by get_args
+                for (int i = 0; i < argc; i++)
+                    free(argv[i]);
+
                 demo.window = (void*)app->window;
                 demo_init_vk_swapchain(&demo);
                 demo_prepare(&demo);