Rootless GPU Debug Tests

This adds a new set of tests that ensure debug Vulkan layers can be
enumerated and loaded from the base dir of debuggable apps.  It also
runs through several positive and negative scenarios to ensure the
new Settings work as expected.

The source builds multiple APKs: DEBUG and RELEASE for testing the
different combinations, and a LAYER APK just for transporting layers.

The layers themselves are null, only containing enough functionality
to be enumerated, chained, and loaded by the Vulkan loader.

Test: cts-tradefed run singleCommand cts -m CtsGpuToolsHostTestCases
Bug: 63708377

Change-Id: I5d1c7c005d4ff8f8629ad91b956d3769987f6170
diff --git a/hostsidetests/gputools/layers/jni/nullLayer.cpp b/hostsidetests/gputools/layers/jni/nullLayer.cpp
new file mode 100644
index 0000000..7253b5c
--- /dev/null
+++ b/hostsidetests/gputools/layers/jni/nullLayer.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2017 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/log.h>
+#include <cstring>
+#include <vulkan/vulkan.h>
+#include "vk_layer_interface.h"
+
+#define xstr(a) str(a)
+#define str(a) #a
+
+#define LOG_TAG "nullLayer" xstr(LAYERNAME)
+
+#define ALOGI(msg, ...) \
+    __android_log_print(ANDROID_LOG_INFO, LOG_TAG, (msg), __VA_ARGS__)
+
+
+// Announce if anything loads this layer.  LAYERNAME is defined in Android.mk
+class StaticLogMessage {
+    public:
+        StaticLogMessage(const char* msg) {
+            ALOGI("%s", msg);
+    }
+};
+StaticLogMessage g_initMessage("nullLayer" xstr(LAYERNAME) " loaded");
+
+
+namespace {
+
+
+// Minimal dispatch table for this simple layer
+struct {
+    PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+} g_VulkanDispatchTable;
+
+
+template<class T>
+VkResult getProperties(const uint32_t count, const T *properties, uint32_t *pCount,
+                            T *pProperties) {
+    uint32_t copySize;
+
+    if (pProperties == NULL || properties == NULL) {
+        *pCount = count;
+        return VK_SUCCESS;
+    }
+
+    copySize = *pCount < count ? *pCount : count;
+    memcpy(pProperties, properties, copySize * sizeof(T));
+    *pCount = copySize;
+    if (copySize < count) {
+        return VK_INCOMPLETE;
+    }
+
+    return VK_SUCCESS;
+}
+
+static const VkLayerProperties LAYER_PROPERTIES = {
+    "VK_LAYER_ANDROID_nullLayer" xstr(LAYERNAME), VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION), 1, "Layer: nullLayer" xstr(LAYERNAME),
+};
+
+VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
+    return getProperties<VkLayerProperties>(1, &LAYER_PROPERTIES, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice /* physicalDevice */, uint32_t *pCount,
+                                                              VkLayerProperties *pProperties) {
+    return getProperties<VkLayerProperties>(0, NULL, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char* /* pLayerName */, uint32_t *pCount,
+                                                                    VkExtensionProperties *pProperties) {
+    return getProperties<VkExtensionProperties>(0, NULL, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice /* physicalDevice */, const char* /* pLayerName */,
+                                                                  uint32_t *pCount, VkExtensionProperties *pProperties) {
+    return getProperties<VkExtensionProperties>(0, NULL, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL nullCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
+                                                  const VkAllocationCallbacks* pAllocator,
+                                                  VkInstance* pInstance) {
+
+    VkLayerInstanceCreateInfo *layerCreateInfo = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext;
+
+    const char* msg = "nullCreateInstance called in nullLayer" xstr(LAYERNAME);
+    ALOGI("%s", msg);
+
+    // Step through the pNext chain until we get to the link function
+    while(layerCreateInfo && (layerCreateInfo->sType != VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO ||
+                              layerCreateInfo->function != VK_LAYER_FUNCTION_LINK)) {
+
+      layerCreateInfo = (VkLayerInstanceCreateInfo *)layerCreateInfo->pNext;
+    }
+
+    if(layerCreateInfo == NULL)
+      return VK_ERROR_INITIALIZATION_FAILED;
+
+    // Grab GIPA for the next layer
+    PFN_vkGetInstanceProcAddr gpa = layerCreateInfo->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+
+    // Track is in our dispatch table
+    g_VulkanDispatchTable.GetInstanceProcAddr = gpa;
+
+    // Advance the chain for next layer
+    layerCreateInfo->u.pLayerInfo = layerCreateInfo->u.pLayerInfo->pNext;
+
+    // Call the next layer
+    PFN_vkCreateInstance createFunc = (PFN_vkCreateInstance)gpa(VK_NULL_HANDLE, "vkCreateInstance");
+    VkResult ret = createFunc(pCreateInfo, pAllocator, pInstance);
+
+    return ret;
+}
+
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice /* dev */, const char* /* funcName */) {
+    return nullptr;
+}
+
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName) {
+
+    // Our simple layer only intercepts vkCreateInstance
+    const char* targetFunc = "vkCreateInstance";
+    if (!strncmp(targetFunc, funcName, sizeof(&targetFunc)))
+        return (PFN_vkVoidFunction)nullCreateInstance;
+
+    return (PFN_vkVoidFunction)g_VulkanDispatchTable.GetInstanceProcAddr(instance, funcName);
+}
+
+}  // namespace
+
+// loader-layer interface v0, just wrappers since there is only a layer
+
+__attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount,
+                                                                  VkLayerProperties *pProperties) {
+    return EnumerateInstanceLayerProperties(pCount, pProperties);
+}
+
+__attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
+                                                                VkLayerProperties *pProperties) {
+    return EnumerateDeviceLayerProperties(physicalDevice, pCount, pProperties);
+}
+
+__attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount,
+                                                                      VkExtensionProperties *pProperties) {
+    return EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
+}
+
+__attribute((visibility("default"))) VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
+                                                                    const char *pLayerName, uint32_t *pCount,
+                                                                    VkExtensionProperties *pProperties) {
+    return EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties);
+}
+
+__attribute((visibility("default"))) VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
+    return GetDeviceProcAddr(dev, funcName);
+}
+
+__attribute((visibility("default"))) VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
+    return GetInstanceProcAddr(instance, funcName);
+}